Gin中使用jwt:发放token、中间件鉴权
Gin中使用jwt:发放token、中间件鉴权
jwt,github地址:
https://github.com/dgrijalva/jwt-go/
前端返回结果的token分析:
//eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOjYsImV4cCI6MTYzNzY2Nzk5OCwiaWF0IjoxNjM3MDYzMTk4LCJpc3MiOiJjaGVuZ3FpYW5nIiwic3ViIjoidXNlciB0b2tlbiJ9.nt8K7vxrAT4XXzh0RbtFveQCyt7J4r1XZnVgDNSVjkQ
//token由三部分组成
//加密协议、荷载(程序信息)、前面两部分+自定义密匙组成的一个哈希值
//使用base64解密保存的信息(分三段进行解密) : echo eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 | base64 -D
jwt配置:common/jwt.go
package common
import (
"github.com/dgrijalva/jwt-go"
"supplierQuerySystemAPICode/model"
"time"
)
//定义秘钥
var jwtKey = []byte("*******")
type Claims struct {
UserId uint
jwt.StandardClaims
}
//登录成功之后发放token
func ReleaseToken(user model.User) (string, error) {
expirationTime := time.Now().Add(7 * 24 * time.Hour) //token的有效期是七天
claims := &Claims{
UserId: user.ID,
StandardClaims: jwt.StandardClaims{
ExpiresAt: expirationTime.Unix(), //token的有效期
IssuedAt: time.Now().Unix(), //token发放的时间
Issuer: "chengqiang", //作者
Subject: "user token", //主题
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString(jwtKey) //根据前面自定义的jwt秘钥生成token
if err != nil {
//返回生成的错误
return "", err
}
//返回成功生成的字符换
return tokenString, nil
}
//eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOjYsImV4cCI6MTYzNzY2Nzk5OCwiaWF0IjoxNjM3MDYzMTk4LCJpc3MiOiJjaGVuZ3FpYW5nIiwic3ViIjoidXNlciB0b2tlbiJ9.nt8K7vxrAT4XXzh0RbtFveQCyt7J4r1XZnVgDNSVjkQ
//token由三部分组成
//加密协议、荷载(程序信息)、前面两部分+自定义密匙组成的一个哈希值
//使用base64解密保存的信息(分三段进行解密) : echo eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 | base64 -D
//解析从前端获取到的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
}
中间件判断前端获取的请求信息,验证通过,获取用户信息id,存入上下文中
package middleware
import (
"fmt"
"github.com/gin-gonic/gin"
"strings"
"supplierQuerySystemAPICode/common"
"supplierQuerySystemAPICode/model"
)
//路由请求中间件,前端必须把token放在请求头上,对服务器进行请求验证token成功后,才能访问后续的请求路由
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 获取 authorization header:获取前端传过来的信息的
tokenString := c.GetHeader("Authorization")
fmt.Print("请求token", tokenString)
//验证前端传过来的token格式,不为空,开头为Bearer
if tokenString == "" || !strings.HasPrefix(tokenString, "Bearer ") {
c.JSON(401, gin.H{
"data": gin.H{
},
"meta": gin.H{
"msg": "权限不足",
"code": 401,
},
})
return
}
//验证通过,提取有效部分(除去Bearer)
tokenString = tokenString[7:] //截取字符
//解析token:common/jwt.go
token, claims, err := common.ParseToken(tokenString)
//解析失败||解析后的token无效
if err != nil || !token.Valid {
c.JSON(401, gin.H{
"data": gin.H{
},
"meta": gin.H{
"msg": "权限不足",
"code": 401,
},
})
return
}
//token通过验证, 获取claims中的UserID
userId := claims.UserId
var user model.User
//查询数据库
common.DB.First(&user, userId)
// 验证用户是否存在
if user.ID == 0 {
c.JSON(401, gin.H{
"data": gin.H{
},
"meta": gin.H{
"msg": "权限不足",
"code": 401,
},
})
}
//用户存在 将user信息写入上下文
c.Set("user", user)
c.Next()
}
}