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

时间:2015-06-06 18:53:10

标签: go

我想在用golang编写的Web应用程序中确定一个简单实用的用户身份验证模式。

我提出了两种模式。第一个是让程序员将他的功能从认证逻辑中分离出来,并且在HandleFunc中有一个更清晰的main()部分,只有通过戳main()才能看到哪些部分在认证中控制。

第二个是让程序员在每个函数中包含一个决定处理身份验证所需的URL。 if语句通过authp()函数检查其他地址。

对于这种必要性哪一个更好的模式?

这项工作有哪些更好的模式?

甚至可以将函数传递给具有func urlFunc (ResponseWriter, *Request)之外的签名的http.HandleFunc,如func urlFunc (successFunc, failFunc)func urlFunc (ResponseWriter, *Request, successFunc, failFunc),如{strong}的authenticationGateKeeper函数第一种方式,如果不是合适的解决方法吗?

//First Way
package main

func authGateKeeper(successFunc, failFunc) {
    if (authp()) {
        successFunc
    } else {
        failFunc
    }
}

func authp() boolean {
    //authentication logic, db query, or session check etc.
}

//usage in main
http.HandleFunc("/", authGateKeeper)



//Second Way; other alternative, in each function check pattern
func 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 main
http.HandleFunc("/", f)

1 个答案:

答案 0 :(得分:4)

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

请注意,我将在此处做一些假设,因为您没有告诉我们您如何管理会话(Cookie?服务器端?)和/或您在身份验证之前可能需要哪种授权

// 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,以便将来帮助您。

如果您想调用自定义错误页面,只需编写一个处理程序 - 例如满足http.Handler的UnauthorizedHandler,在此过程中只需拨打UnauthorizedHandler.ServeHTTP(w, r)而不是http.Error