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 Claims
mySigningKey := []byte(SecretKEY)
expireAt := time.Now().Add(time.Second * time.Duration(expiredSeconds)).Unix()
logs.Info("Token will be expired at ", time.Unix(expireAt, 0))
user := *loginInfo
claims := MyCustomClaims{
userID,
jwt.StandardClaims{
Issuer: user.Username,
IssuedAt: time.Now().Unix(),
ExpiresAt: expireAt,
},
}
// Create the token using your claims
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// Signs the token with a secret
tokenStr, 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 header
u.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 password
username := lr.Username
password := lr.Password
//validate username and password if is empty
if len(username) == 0 || len(password) == 0 {
return nil, http.StatusBadRequest, errors.New("error: username or password is empty")
}
// connect db
o := orm.NewOrm()
// check the username if existing
user := &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 hash
hash, 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 token
tokenString, 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 db
o := orm.NewOrm()
// check username if exist
userNameCheck := User{Username: cr.Username}
err := o.Read(&userNameCheck, "username")
if err == nil {
return nil, http.StatusBadRequest, errors.New("username has already existed")
}
// generate salt
saltKey, err := GenerateSalt()
if err != nil {
logs.Info(err.Error())
return nil, http.StatusBadRequest, err
}
// generate password hash
hash, err := GeneratePassHash(cr.Password, saltKey)
if err != nil {
logs.Info(err.Error())
return nil, http.StatusBadRequest, err
}
// create user
user := User{}
user.Username = cr.Username
user.Password = hash
user.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
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。