基于 Golang 会话的身份验证

Golang session based authentication

我正在尝试在 golang 中验证用户身份(使用电子邮件和密码),但我在会话方面遇到了一些问题。似乎我无法从 /login/ 检索会话值到 / (主页)页面。

用户注册

hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(r.Form["passwordSignup"][0]), bcrypt.DefaultCost)

err = c.Insert(&model.UserModel{
  Email:     r.Form["emailSignup"][0],
  Password:  string(hashedPassword),
  CreatedAt: time.Now(),
})

// TODO : should session management be made in here ???
// you can use gorilla sessions if you want as far it works

http.SetCookie(w, cookie)
http.Redirect(w, r, "/", 301) // goes to the homepage(only accessed by authenticated users)

登录

if r.Form["emailLogin"][0] == result.Email 
&& bcrypt.CompareHashAndPassword([]byte(result.Password), []byte(r.Form["passwordLogin"][0])) == nil {

  // TODO : Handling the session in here

  http.Redirect(w, r, "/", 301) // goes to the home page
} else {
  http.Redirect(w, r, "/login/", 301)
}

我也检查了这个链接: http://shadynasty.biz/blog/2012/09/05/auth-and-sessions/ https://www.youtube.com/watch?v=p0tGnjW_xxI

重要的是,您应该检查所有错误 - 例如:

- hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(r.Form["passwordSignup"][0]), bcrypt.DefaultCost)
# Check our error, especially for something as important as password hashing
+ hashedPassword, err := bcrypt.GenerateFromPassword([]byte(r.Form["passwordSignup"][0]), bcrypt.DefaultCost)
if err != nil {
    http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
    return
}

您的许多相关 cookie 代码丢失了,但它应该 如下所示:

cookie := &http.Cookie{
        Name: "my_app",
        Value: val, // Some encoded value
        Path: "/", // Otherwise it defaults to the /login if you create this on /login (standard cookie behaviour)
        MaxAge: 86400, // One day
}

http.SetCookie(w, cookie)

或者,如果您使用 gorilla/sessions(我推荐它,因为它可以正确验证 cookie),您可以执行以下操作:

session, err := store.Get(r, "session-name")
if err != nil {
    http.Error(w, err.Error(), 500)
    return
}

session.Options.Path = "/"
session.Values["user"] = user

err := session.Save(r, w)
if err != nil {
    http.Error(w, err.Error(), 500)
    return
}

http.Redirect(w, r, "/", 301)

如果您正在寻找使用 Redis 或 Memcache 作为会话存储的简单会话管理解决方案,我建议使用 Jeff(免责声明:我写的)。

对用户进行身份验证后,您只需像这样添加他们的会话:

func (s Server) Login(w http.ResponseWriter, r *http.Request) {
    user = Authenticate(r)
    if user != nil {
        // Key must be unique to one user among all users
        err := s.jeff.Set(r.Context(), w, user.Email)
        // handle error
    }
    // finish login
}

使用 Jeff 中间件包装后,后续请求将自动进行身份验证。该库的构建考虑到了简单性,并且是作为现有库的替代品而构建的。

有关用法和功能的更多详细信息,请参阅自述文件:

https://github.com/abraithwaite/jeff#usage