jwt验证登录token
用户输入账号密码,后端密码验证通过,返回一个token对象。这样后端就可以为无状态的,每次请求的时候,请求头带上token ,里面封装了对象的信息,我们用拦截器(自己在gin中实现拦截器)进行拦截,解析token,后端就可以知道是谁登录了界面,可以设置相应的超时时间超时用户就需要从新登录。
其中代码模型为:
登录的 HandlerFunc 中,需要生成 token,并设置响应头带上这个 token
中间件可以处理分组的请求,检测 Authorization 中数据做解析判定数据是否有效,如果无效直接返回无权限,不会进入到具体 HandlerFunc 中操作,如果有效则把 claims 中的用户信息保存到 gin.context 中,然后放行进入 HandlerFunc 中
登录成功发放token
//密码正确发放token给前端
token,err:=common.ReleaseToken(user)
if err!=nil{
ctx.JSON(http.StatusInternalServerError,gin.H{"code":500,"msg":"系统异常"})
return
}
其中ReleaseToken为
//发放token
func ReleaseToken(user model.User) (string,error){
//token的有效期
expirationTime:=time.Now().Add(7*24*time.Hour)
//创建一个claims
Claims:=&Claims{
UserID: user.ID,
StandardClaims: jwt.StandardClaims{
//过期时间
ExpiresAt: expirationTime.Unix(),
//签名时间
IssuedAt: time.Now().Unix(),
//签名颁发者
Issuer: "hsm",
//签名主题
Subject: "user token",
},
}
// 使用指定的签名加密方式创建 token
token:=jwt.NewWithClaims(jwt.SigningMethodHS256,Claims)
//使用 secretKey 密钥进行加密处理后拿到最终 token string
tokenString,err:=token.SignedString(jwtKey)
if err!=nil{
return "",err
}
return tokenString,nil
}
AuthMiddleware
//认证中间件
func AuthMiddleware() gin.HandlerFunc{
return func(ctx *gin.Context) {
//获取authorization header
tokenString :=ctx.GetHeader("Authorization")
//验证token的格式
if tokenString ==""|| !strings.HasPrefix(tokenString,"Bearer "){
ctx.JSON(http.StatusUnauthorized,gin.H{"code":401,"msg":"权限不足"})
//抛弃该次请求
ctx.Abort()
return
}
//提取token的有效部分
tokenString=tokenString[7:]
//解析token失败或解析到的token无效,则返回权限不足
token,claims,err:=common.ParseToken(tokenString)
if err!=nil ||!token.Valid{
ctx.JSON(http.StatusUnauthorized,gin.H{"code":401,"msg":"权限不足"})
ctx.Abort()
return
}
//否则证明token通过了验证,其中claims是解析出token的有效部分,获取claims中的userid
userId:=claims.UserID
db:=common.GetDB()
var user model.User
db.First(&user,userId)
//用户不存在
if userId==0{
ctx.JSON(http.StatusUnauthorized,gin.H{"code":401,"msg":"权限不足"})
ctx.Abort()
return
}
//用户存在,将user信息写入上下文中
ctx.Set("user",user)
//执行路由 HandlerFunc
ctx.Next()
}
}