定义
token的意思是“令牌”,在代码中本质上是一种字符串,是用户身份的验证方式。
使用方式
- 在登陆时,服务端接收到客户端发来的登录信息(账号密码),在数据库中校验成功后,生成一个token,并将其响应给客户端。每个token对应一个用户。
- 客户端接收到token后,将其存储起来,之后每次调取后端接口时,都要在请求头中加上token。
- 服务端在后续的接口中,可以获取到请求头中的token,进而获取到token中附带的用户基本信息。
代码实现
1. 生成Token
在登录接口中,我们核对用户账号密码正确后,即可生成该用户的token。
// 生成token的密钥
var JwtKey = []byte("hahahahha") // 小项目密钥值随便定义
// 存放关于token的基本信息
type Claims struct {
User gorm_model.User // 附带的该用户的信息
jwt.StandardClaims
}
// 生成token
func ReleaseToken(user gorm_model.User) (tokenString string,err error) {
expire := time.Now().Add(7 * 24 * time.Hour)
claims := &Claims{
User: user, // 用户个人信息
StandardClaims: jwt.StandardClaims{
ExpiresAt: expire.Unix(), //token的有效时长
IssuedAt: time.Now().Unix(), //token的创建时间
Issuer: "xunxun", //作者
Subject: "user token", //主题
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err = token.SignedString(jwtKey) //根据前面自定义的Jwt秘钥生成token
tokenString = "Bearer " + tokenString
if err != nil {
return "", err
}
return tokenString, nil
}
2. 解析Token
在生成完token并完成登录之后,后续的业务中,我们如何通过token获取到用户信息呢?我们先获取到请求头中的token,将其进行解析,解析之后就能取到其包含的用户信息。信息就包含在Claims结构体对象中。
// 解析token
func ParseToken(tokenString string) (*jwt.Token, *Claims, error) {
claims := &Claims{}
token,err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
return jwtKey, nil
})
return token, claims, err
}
3.定义token中间件
token中间件用于判断token是否有效,并将用户信息注入到gin.Context中。这一步是必须要的,是项目安全性的保证。
// AuthMiddleware 中间件检验token是否合法
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 获取请求头中的token
tokenString := c.GetHeader("token")
//验证token格式,不为空,开头为Bearer
if tokenString == "" || !strings.HasPrefix(tokenString, "Bearer ") {
response.ResponseErrorWithMsg(c, 400, "token不合法")
c.Abort()
return
}
//验证通过,提取有效部分(除去Bearer)
tokenString = tokenString[7:] //截取字符
//解析token
token, _, err := ParseToken(tokenString)
//解析失败||解析后的token无效
if err != nil || !token.Valid {
response.ResponseErrorWithMsg(c, 400, "token解析失败")
c.Abort()
return
}
c.Set("claim", token.Claims)
c.Next()
}
}
4. 给需要用到token的接口加上该token中间件
5. 在接口中获取到token附带的用户信息
tokenString := c.GetHeader("token") // 获取到请求头中的token
tokenString = tokenString[7:]
token, _, _ := token.ParseToken(tokenString) // 解析token
user := token.Claims.(*models.Claims).User // 获取到token中附带的用户信息