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