1. Beego 安装
安装或者升级 Beego 和 Bee 的开发工具:
go get -u github.com/astaxie/beego
go get -u github.com/beego/bee
Beego是快速开发 Go 应用的 HTTP 框架,可以用来快速开发 API、Web 及后端服务等各种应用,其官方教程 https://beego.me/quickstart
2. JWT 安装
go get github.com/dgrijalva/jwt-go
JWT(Json web token) 是目前最流行的跨域认证解决方案之一,其官网文档 https://jwt.io/introduction/
3. Beego + JWT 实现登录注册
(1)Jwt 实现
// generate token
func GenerateToken(loginInfo *LoginRequest, userID int, expiredSeconds int) (tokenString string, err error) {if expiredSeconds == 0 {expiredSeconds = DEFAULT_EXPIRE_SECONDS}// Create the ClaimsmySigningKey := []byte(SecretKEY)expireAt := time.Now().Add(time.Second * time.Duration(expiredSeconds)).Unix()logs.Info("Token will be expired at ", time.Unix(expireAt, 0))user := *loginInfoclaims := MyCustomClaims{userID,jwt.StandardClaims{Issuer: user.Username,IssuedAt: time.Now().Unix(),ExpiresAt: expireAt,},}// Create the token using your claimstoken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)// Signs the token with a secrettokenStr, err := token.SignedString(mySigningKey)if err != nil {return "", errors.New("error: failed to generate token")}return tokenStr, nil
}
(2)controller(登录和注册)
// Login handles login request
func (u *UserController) Login() {lr := new(models.LoginRequest)if err := u.unmarshalPayload(lr); err != nil {u.respond(http.StatusBadRequest, err.Error())return}lrs, statusCode, err := models.DoLogin(lr)if err != nil {u.respond(statusCode, err.Error())return}u.Ctx.Output.Header("Authorization", lrs.Token) // set token into headeru.respond(http.StatusOK, "", lrs)
}// CreateUser creates a user
func (u *UserController) CreateUser() {cu := new(models.CreateRequest)if err := u.unmarshalPayload(cu); err != nil {u.respond(http.StatusBadRequest, err.Error())}createUser, statusCode, err := models.DoCreateUser(cu)if err != nil {u.respond(statusCode, err.Error())return}u.respond(http.StatusOK, "", createUser)
}
(3)model(登录和注册)
// DoLogin: user login
func DoLogin(lr *LoginRequest) (*LoginResponse, int, error) {// get username and passwordusername := lr.Usernamepassword := lr.Password//validate username and password if is emptyif len(username) == 0 || len(password) == 0 {return nil, http.StatusBadRequest, errors.New("error: username or password is empty")}// connect dbo := orm.NewOrm()// check the username if existinguser := &User{Username: username}err := o.Read(user, "username")if err != nil {return nil, http.StatusBadRequest, errors.New("error: username is not existing")}// generate the password hashhash, err := GeneratePassHash(password, user.Salt)if err != nil {return nil, http.StatusBadRequest, err}if hash != user.Password {return nil, http.StatusBadRequest, errors.New("error: password is error")}// generate tokentokenString, err := GenerateToken(lr, user.Id, 0)if err != nil {return nil, http.StatusBadRequest, err}return &LoginResponse{Username: user.Username,UserID: user.Id,Token: tokenString,}, http.StatusOK, nil
}// DoCreateUser: create a user
func DoCreateUser(cr *CreateRequest) (*CreateResponse, int, error) {// connect dbo := orm.NewOrm()// check username if existuserNameCheck := User{Username: cr.Username}err := o.Read(&userNameCheck, "username")if err == nil {return nil, http.StatusBadRequest, errors.New("username has already existed")}// generate saltsaltKey, err := GenerateSalt()if err != nil {logs.Info(err.Error())return nil, http.StatusBadRequest, err}// generate password hashhash, err := GeneratePassHash(cr.Password, saltKey)if err != nil {logs.Info(err.Error())return nil, http.StatusBadRequest, err}// create useruser := User{}user.Username = cr.Usernameuser.Password = hashuser.Salt = saltKey_, err = o.Insert(&user)if err != nil {logs.Info(err.Error())return nil, http.StatusBadRequest, err}return &CreateResponse{UserID: user.Id,Username: user.Username,}, http.StatusOK, nil}
完整的代码可见github: https://github.com/Messi-Q/Beego-Jwt