根据某些句柄请求对用户进行身份验证

时间:2019-04-05 02:03:33

标签: rest go mux

是否存在更有效的方式来对某些句柄请求进行身份验证?现在,我正在调用一个基于请求令牌进行身份验证的函数,但是正在为每个句柄函数执行此操作。

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 个答案:

答案 0 :(得分: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的函数作为参数。在这种情况下,哪个是处理程序本身。

  

func处理程序(w http.ResponseWriter,r * http.Request)

因此,该函数必须具有http.ResponseWriter和* http.Request作为参数。这与http.HandleFunc要求的相同。

  

http.HandleFunc(“ / your / url / path”,处理程序)

grant函数的工作基本上是将处理程序作为参数,如果一切顺利,grant将以与http.HandleFunc相同的方式执行处理程序。

  

fn(w,r)

如果身份验证失败,则Grant将返回错误,并且永远不会执行处理程序。