From bbaf71481cf7bf559f21469d737b7bbdc6d09a55 Mon Sep 17 00:00:00 2001 From: duoyun Date: Sun, 6 Sep 2015 23:16:56 +0800 Subject: [PATCH] use bcrypt and keep Md5 --- app/controllers/AuthController.go | 32 ++++++++++--------- app/controllers/admin/AdminEmailController.go | 5 ++- .../admin/AdminSettingController.go | 6 +++- app/controllers/api/ApiAuthController.go | 12 +++---- app/crypto/crypto.go | 26 +++++++++++++++ app/service/AuthService.go | 28 ++++++++++++---- app/service/PwdService.go | 10 ++++-- app/service/UserService.go | 14 ++++++++ 8 files changed, 101 insertions(+), 32 deletions(-) create mode 100644 app/crypto/crypto.go diff --git a/app/controllers/AuthController.go b/app/controllers/AuthController.go index 6af77e7..de52dc8 100644 --- a/app/controllers/AuthController.go +++ b/app/controllers/AuthController.go @@ -41,15 +41,15 @@ func (c Auth) doLogin(email, pwd string) revel.Result { sessionId := c.Session.Id() var msg = "" - userInfo := authService.Login(email, pwd) - if userInfo.Email != "" { + userInfo, err := authService.Login(email, pwd) + if err != nil { + // 登录错误, 则错误次数++ + msg = "wrongUsernameOrPassword" + } else { c.SetSession(userInfo) sessionService.ClearLoginTimes(sessionId) return c.RenderJson(info.Re{Ok: true}) - } else { - // 登录错误, 则错误次数++ - msg = "wrongUsernameOrPassword" - } + } return c.RenderJson(info.Re{Ok: false, Item: sessionService.LoginTimesIsOver(sessionId) , Msg: c.Message(msg)}) } @@ -61,16 +61,16 @@ func (c Auth) DoLogin(email, pwd string, captcha string) revel.Result { if sessionService.LoginTimesIsOver(sessionId) && sessionService.GetCaptcha(sessionId) != captcha { msg = "captchaError" } else { - userInfo := authService.Login(email, pwd) - if userInfo.Email != "" { - c.SetSession(userInfo) - sessionService.ClearLoginTimes(sessionId) - return c.RenderJson(info.Re{Ok: true}) - } else { + userInfo, err := authService.Login(email, pwd) + if err != nil { // 登录错误, 则错误次数++ msg = "wrongUsernameOrPassword" sessionService.IncrLoginTimes(sessionId) - } + } else { + c.SetSession(userInfo) + sessionService.ClearLoginTimes(sessionId) + return c.RenderJson(info.Re{Ok: true}) + } } return c.RenderJson(info.Re{Ok: false, Item: sessionService.LoginTimesIsOver(sessionId) , Msg: c.Message(msg)}) @@ -87,8 +87,10 @@ func (c Auth) Logout() revel.Result { func (c Auth) Demo() revel.Result { email := configService.GetGlobalStringConfig("demoPassword") pwd := configService.GetGlobalStringConfig("demoPassword"); - userInfo := authService.Login(email, pwd) - if userInfo.Email != "" { + userInfo, err := authService.Login(email, pwd) + if err != nil { + return c.RenderJson(info.Re{Ok: false}) + } else { c.SetSession(userInfo) return c.Redirect("/note") } diff --git a/app/controllers/admin/AdminEmailController.go b/app/controllers/admin/AdminEmailController.go index b12494f..86fc766 100644 --- a/app/controllers/admin/AdminEmailController.go +++ b/app/controllers/admin/AdminEmailController.go @@ -46,7 +46,10 @@ func (c AdminEmail) Demo() revel.Result { func (c AdminEmail) DoDemo(demoUsername, demoPassword string) revel.Result { re := info.NewRe() - userInfo := authService.Login(demoUsername, demoPassword) + userInfo, err := authService.Login(demoUsername, demoPassword) + if err != nil { + return c.RenderJson(info.Re{Ok: false}) + } if userInfo.UserId == "" { re.Msg = "The User is Not Exists"; return c.RenderJson(re) diff --git a/app/controllers/admin/AdminSettingController.go b/app/controllers/admin/AdminSettingController.go index 8a4ce51..abda4b9 100644 --- a/app/controllers/admin/AdminSettingController.go +++ b/app/controllers/admin/AdminSettingController.go @@ -56,7 +56,11 @@ func (c AdminSetting) Demo() revel.Result { func (c AdminSetting) DoDemo(demoUsername, demoPassword string) revel.Result { re := info.NewRe() - userInfo := authService.Login(demoUsername, demoPassword) + userInfo, err := authService.Login(demoUsername, demoPassword) + if err != nil { + fmt.Println(err) + return c.RenderJson(info.Re{Ok: false}) + } if userInfo.UserId == "" { re.Msg = "The User is Not Exists"; return c.RenderJson(re) diff --git a/app/controllers/api/ApiAuthController.go b/app/controllers/api/ApiAuthController.go index e4f35aa..f732462 100644 --- a/app/controllers/api/ApiAuthController.go +++ b/app/controllers/api/ApiAuthController.go @@ -24,15 +24,15 @@ type ApiAuth struct { func (c ApiAuth) Login(email, pwd string) revel.Result { var msg = "" - userInfo := authService.Login(email, pwd) - if userInfo.Email != "" { + userInfo, err := authService.Login(email, pwd) + if err != nil { + // 登录错误, 则错误次数++ + msg = "wrongUsernameOrPassword" + } else { token := bson.NewObjectId().Hex() sessionService.SetUserId(token, userInfo.UserId.Hex()) return c.RenderJson(info.AuthOk{Ok: true, Token: token, UserId: userInfo.UserId, Email: userInfo.Email, Username: userInfo.Username}) - } else { - // 登录错误, 则错误次数++ - msg = "wrongUsernameOrPassword" - } + } return c.RenderJson(info.ApiRe{Ok: false, Msg: c.Message(msg)}) } diff --git a/app/crypto/crypto.go b/app/crypto/crypto.go new file mode 100644 index 0000000..2c0d526 --- /dev/null +++ b/app/crypto/crypto.go @@ -0,0 +1,26 @@ +// Package crypto contains two cryptographic functions for both storing and comparing passwords. +package crypto + +import ( + "golang.org/x/crypto/bcrypt" +) + +// GenerateHash generates bcrypt hash from plaintext password +func GenerateHash(password string) ([]byte, error) { + hex := []byte(password) + hashedPassword, err := bcrypt.GenerateFromPassword(hex, 10) + if err != nil { + return hashedPassword, err + } + return hashedPassword, nil +} + +// CompareHash compares bcrypt password with a plaintext one. Returns true if passwords match +// and false if they do not. +func CompareHash(digest []byte, password string) bool { + hex := []byte(password) + if err := bcrypt.CompareHashAndPassword(digest, hex); err == nil { + return true + } + return false +} diff --git a/app/service/AuthService.go b/app/service/AuthService.go index be6310c..03f735c 100644 --- a/app/service/AuthService.go +++ b/app/service/AuthService.go @@ -4,11 +4,13 @@ import ( "gopkg.in/mgo.v2/bson" // "github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/info" + . "github.com/leanote/leanote/app/crypto" // "github.com/revel/revel" "strings" . "github.com/leanote/leanote/app/lea" "fmt" "strconv" + "errors" ) // 登录与权限 @@ -16,12 +18,21 @@ import ( type AuthService struct { } -// pwd已md5了 -func (this *AuthService) Login(emailOrUsername, pwd string) info.User { +// 使用bcrypt认证或者Md5认证 +func (this *AuthService) Login(emailOrUsername, pwd string) (info.User, error) { emailOrUsername = strings.Trim(emailOrUsername, " ") -// pwd = strings.Trim(pwd, " ") - userInfo := userService.LoginGetUserInfo(emailOrUsername, Md5(pwd)) - return userInfo + // pwd = strings.Trim(pwd, " ") + userInfo := userService.GetUserInfoByName(emailOrUsername) + passwd := userInfo.Pwd + if len(passwd) == 32 && Md5(pwd) != passwd { + return userInfo, errors.New("wrong username or password") + } else { + hex := []byte(passwd) + if !CompareHash(hex, pwd) { + return userInfo, errors.New("wrong username or password") + } + } + return userInfo, nil } // 注册 @@ -40,7 +51,12 @@ func (this *AuthService) Register(email, pwd, fromUserId string) (bool, string) if userService.IsExistsUser(email) { return false, "userHasBeenRegistered-" + email } - user := info.User{UserId: bson.NewObjectId(), Email: email, Username: email, Pwd: Md5(pwd)} + digest, err := GenerateHash(pwd) + if err != nil { + return false,"GenerateHash error" + } + passwd := string(digest) + user := info.User{UserId: bson.NewObjectId(), Email: email, Username: email, Pwd: passwd} if fromUserId != "" && IsObjectId(fromUserId) { user.FromUserId = bson.ObjectIdHex(fromUserId) } diff --git a/app/service/PwdService.go b/app/service/PwdService.go index 715b1a7..2c72c69 100644 --- a/app/service/PwdService.go +++ b/app/service/PwdService.go @@ -4,7 +4,7 @@ import ( "gopkg.in/mgo.v2/bson" "github.com/leanote/leanote/app/db" "github.com/leanote/leanote/app/info" - . "github.com/leanote/leanote/app/lea" + . "github.com/leanote/leanote/app/crypto" ) // 找回密码 @@ -45,9 +45,13 @@ func (this *PwdService) UpdatePwd(token, pwd string) (bool, string) { if ok, msg, tokenInfo = tokenService.VerifyToken(token, info.TokenPwd); !ok { return ok, msg } - + digest, err := GenerateHash(pwd) + if err != nil { + return false,"GenerateHash error" + } + passwd := string(digest) // 修改密码之 - ok = db.UpdateByQField(db.Users, bson.M{"_id": tokenInfo.UserId}, "Pwd", Md5(pwd)) + ok = db.UpdateByQField(db.Users, bson.M{"_id": tokenInfo.UserId}, "Pwd", passwd) // 删除token tokenService.DeleteToken(tokenInfo.UserId.Hex(), info.TokenPwd) diff --git a/app/service/UserService.go b/app/service/UserService.go index d51c014..0b2e757 100644 --- a/app/service/UserService.go +++ b/app/service/UserService.go @@ -253,6 +253,20 @@ func (this *UserService) LoginGetUserInfo(emailOrUsername, md5Pwd string) info.U return user } +// 使用email(username), 得到用户信息 +func (this *UserService) GetUserInfoByName(emailOrUsername string) info.User { + emailOrUsername = strings.ToLower(emailOrUsername) + + user := info.User{} + if strings.Contains(emailOrUsername, "@") { + db.GetByQ(db.Users, bson.M{"Email": emailOrUsername}, &user) + } else { + db.GetByQ(db.Users, bson.M{"Username": emailOrUsername}, &user) + } + this.setUserLogo(&user) + return user +} + // 更新username func (this *UserService) UpdateUsername(userId, username string) (bool, string) { if userId == "" || username == "" || username == "admin" { // admin用户是内置的, 不能设置