为了账号安全,请及时绑定邮箱和手机立即绑定

Web 应用程序中的 Go- 身份验证逻辑模式

Web 应用程序中的 Go- 身份验证逻辑模式

Go
扬帆大鱼 2021-10-11 13:50:17
我想在用 golang 编写的 Web 应用程序中确定一种简单而有用的用户身份验证模式。我想出了两种模式。第一个是使程序员能够将他的功能与身份验证逻辑分开,并且具有更清晰的HandleFunc部分,main()因为人们只能通过main()查看哪些部分在身份验证控制下才能看到。第二个是让程序员在每个函数中包含一个处理身份验证所需 url 的决定。一个if由语句检查authp()功能,其他地方定义。对于这种必要性,哪一种是更好的模式?这项工作的更好模式是什么?如果不是一个合适的解决方法,是否甚至可以将一个函数传递给 http.HandleFunc,该函数具有除func urlFunc (ResponseWriter, *Request)bu likefunc urlFunc (successFunc, failFunc)或func urlFunc (ResponseWriter, *Request, successFunc, failFunc)as in authenticationGateKeeperfunction of First Way以外的签名?//First Waypackage mainfunc authGateKeeper(successFunc, failFunc) {    if (authp()) {        successFunc    } else {        failFunc    }}func authp() boolean {    //authentication logic, db query, or session check etc.}//usage in mainhttp.HandleFunc("/", authGateKeeper)//Second Way; other alternative, in each function check patternfunc f(w, r) {    if (authp()) {    //function's processes    } else {    //the fail case function or processes    }}func authp() boolean {    //authentication logic, db query, or session check etc.}//usage in mainhttp.HandleFunc("/", f)
查看完整描述

1 回答

?
BIG阳

TA贡献1859条经验 获得超6个赞

有很多方法可以解决这个问题,其中一种是否完全“更好”是有争议的。我强烈建议编写一些中间件来包装您的路由并强制执行检查,仅在成功时调用包装的处理程序。


请注意,我将在这里做一些假设,因为您没有告诉我们您如何管理会话(cookies?服务器端?)和/或除了身份验证之外您可能需要什么样的授权。


// Middleware - a function that sits in the 'middle' of your request processing.

func RequireAuth(h http.Handler) http.Handler) {

    fn := func(w http.ResponseWriter, r *http.Request) {

        // Assuming gorilla/sessions

        session, err := store.Get("name", r)

        if err != nil {

            // Raise HTTP 500

            return

        }


        // We'll assume you're storing the userID in the cookie|server session

        // upon login elsewhere.

        id := session.Values["userID"]

        // Probably returns a *yourapp.User

        user, err := db.GetUser(id)

        if err != nil {

            // Raise HTTP 500

            return

        }


        if user == nil {

            http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)

            // Don't forget these 'naked' returns - if you miss one, your 

            // handler will keep processing beyond the error and result in

            // unintended side effects

            return

        }


        // Further checks here - i.e. checking user.Active == true, etc.


        // The userID matches one in the DB, so let's proceed

        h.ServeHTTP(w, r)

    }


    return http.HandlerFunc(fn)

}


// And in your router - assuming just vanilla net/http

http.Handle("/", RequireAuth(yourHandlerFunc))

http.Handle("/", RequireAuth(someOtherHandler))

// Note that using gorilla/mux or goji can help give you "subrouters" so you

// don't have to wrap every single route with your middleware (messy, error prone)

我还建议您阅读有关 Go 中间件1组合2 的一些内容,这将对您将来有所帮助。


如果您想调用自定义错误页面,只需编写一个处理程序 - 例如UnauthorizedHandler,满足 http.Handler 并且只是调用UnauthorizedHandler.ServeHTTP(w, r)而不是http.Error沿途调用。


查看完整回答
反对 回复 2021-10-11
  • 1 回答
  • 0 关注
  • 156 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信