#rest #go #mux
#rest #Вперед #Мультиплексирование
Вопрос:
Существует ли более эффективный способ аутентификации пользователей при определенных запросах дескриптора? Прямо сейчас я вызываю функцию для аутентификации на основе токена запроса, но делаю это для каждой функции дескриптора.
func GetCompanies(w http.ResponseWriter, r *http.Request) {
//Authentication
token := r.Header.Get("Authorization")
err := auth.AuthenticateUser(token)
if err != nil {
if custom, ok := err.(*errors.MyErrorType); ok {
fmt.Println(custom.Error())
w.WriteHeader(custom.Code)
_ = json.NewEncoder(w).Encode("Error: " custom.Msg)
} else {
fmt.Println(err)
w.WriteHeader(500)
}
return
}
//If user is authenticated do other stuff
}
Я пробовал использовать промежуточное программное обеспечение, но оно выполняется для каждой функции дескриптора. Я хочу, чтобы пользователи, не прошедшие проверку подлинности, получали доступ к определенным API
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Do stuff here
fmt.Println(r.URL)
// Call the next handler, which can be another middleware in the chain, or the final handler.
next.ServeHTTP(w, r)
})
}
func HandleFunctions() {
//Init Router
r := mux.NewRouter()
r.Use(loggingMiddleware)
//API Paths that do not require Auth
r.HandleFunc("/login", handlers.Authenticate).Methods("POST")
//API Paths that require auth
r.HandleFunc("/stuff", handlers.PostThings).Methods("POST")
}
Я также хочу иметь возможность реализовывать роли пользователей в будущем, чтобы в зависимости от разрешений безопасности были доступны разные пути или нет.
Какой наиболее эффективный способ сделать это?
Ответ №1:
На самом деле вам не нужно промежуточное программное обеспечение для этого. Вы можете достичь этого, обернув свои обработчики в общую функцию аутентификации. Взгляните на приведенный ниже код, я думаю, он сделает то, что вы ищете.
func grant(fn func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
//Place your logic to authenticate users here
//This is only a snippet. You have to adapt the code to your needs.
token := r.Header.Get("Authorization")
if err := auth.AuthenticateUser(token); err != nil {
//If error is returned. The grant function will return error
// and abort execution and therefore not reaching your handler
http.Error(w, "Authentication is Invalid", http.StatusInternalServerError)
return
}
//If Authentication is valid your handler function will be executed
fn(w, r)
}
}
// Define your handler functions as you'd normally do
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w,"Success")
}
func main() {
//Then wrap the handlers that need authentication around the grant function
http.HandleFunc("/your/url/path", grant(handler))
//For endpoints that don't need authentication, simply pass the handler as usual without the grant function
http.HandleFunc("/your/url/path/noauth", anotherHandler)
}
Функция «grant» принимает функцию типа http.HandlerFunc в качестве аргумента. Который в данном случае является самим обработчиком.
функциональный обработчик (w http.ResponseWriter, r * http.Запрос)
Следовательно, функция должна иметь http.ResponseWriter и *http.Запрашивать в качестве аргументов. Что является тем же самым, что требуется http.Функция обработки.
http.HandleFunc(«/ваш/url/путь», обработчик)
То, что делает функция grant, в основном принимает ваш обработчик в качестве аргумента, и если все идет хорошо, grant выполняет ваш обработчик таким же образом, как http.HandleFunc бы подошел.
fn (w, r)
Если аутентификация завершится неудачей, grant вернет ошибку и никогда не достигнет выполнения вашего обработчика.
Комментарии:
1. Это сработало. Не могли бы вы объяснить части этой функции, чтобы я понял, что происходит?
unc grant(fn func(http.ResponseWriter, *http.Request)) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request)