package account import ( "crypto/rand" "crypto/sha512" "encoding/hex" "encoding/json" "log" "reflect" "strings" "git.trj.tw/golang/go-gallery/modules/memstore" "git.trj.tw/golang/go-gallery/models" "git.trj.tw/golang/go-gallery/modules/context" "git.trj.tw/golang/go-gallery/modules/utils" "golang.org/x/crypto/pbkdf2" ) var passIterator = 2048 var passLen = 64 var passSaltLen = 16 var passHash = sha512.New // UserLogin route func UserLogin(c *context.Context) { loginArg := struct { Account string `form:"account" json:"account" binding:"required"` Password string `form:"password" json:"password" binding:"required"` }{ Account: "", Password: "", } err := c.BindData(&loginArg) if err != nil { c.DataFormat(nil) return } acc, err := models.GetAccount(loginArg.Account) if err != nil { log.Println(err) c.ServerError(nil) return } if acc == nil { c.NotFound("User not found") return } strs := strings.Split(acc.Password, ".") if len(strs) != 2 { c.ServerError("store pass format error") return } b, err := hex.DecodeString(strs[0]) if err != nil { c.ServerError(nil) return } hashPass, err := hex.DecodeString(strs[1]) if err != nil { c.ServerError(nil) return } enc := pbkdf2.Key([]byte(loginArg.Password), b, passIterator, passLen, passHash) if enc == nil || !reflect.DeepEqual(enc, hashPass) { c.DataFormat("password error") return } res := utils.ToMap(acc) m := make(map[string]interface{}) m["user"] = res jsonStr, err := json.Marshal(m) if err != nil { c.ServerError(nil) return } tByte := make([]byte, 20) _, err = rand.Read(tByte) if err != nil { c.ServerError(nil) return } err = memstore.RedisSet("golang", hex.EncodeToString(tByte), string(jsonStr), 600) if err != nil { c.ServerError(nil) } m["token"] = hex.EncodeToString(tByte) c.Success(m) } // UserLogout route func UserLogout(c *context.Context) { token := c.GetHeader("X-Auth-Token") if len(token) == 0 { c.DataFormat("token not found") return } err := memstore.RedisDel("golang", token) if err != nil { c.ServerError("remvoe session fail") return } c.Success(nil) } // UserSignup route func UserSignup(c *context.Context) { singupObj := struct { Account string `json:"account" binding:"required"` Password string `json:"password" binding:"required"` Nick string `json:"nick"` Email string `json:"email" binding:"required"` }{} err := c.BindData(&singupObj) if err != nil { c.DataFormat(nil) return } salt := make([]byte, passSaltLen) _, err = rand.Read(salt) if err != nil { c.ServerError(nil) return } passBuf := pbkdf2.Key([]byte(singupObj.Password), salt, passIterator, passLen, passHash) passStr := hex.EncodeToString(salt) + "." + hex.EncodeToString(passBuf) dat, err := models.GetAccount(singupObj.Account) if err != nil { c.ServerError(nil) return } if dat != nil { c.DataFormat("account exists") return } dat = nil acc := &models.Account{} acc.Account = singupObj.Account acc.Nick = singupObj.Nick acc.Password = passStr acc.Email = singupObj.Email err = acc.Create() if err != nil { c.ServerError(nil) return } ok, err := acc.Get() if !ok { c.ServerError(nil) return } log.Println(acc.ID) c.Success(nil) }