gin框架中JWT的使用

发布时间 2023-04-14 22:08:02作者: yangphp

前言:

Token Session

Session 是一种记录服务器和客户端会话状态的机制,使服务端有状态化,可以记录会话信息。

Token 是令牌,访问资源接口(API)时所需要的资源凭证。Token 使服务端无状态化,不会存储会话信息。

正文:

Gin  JWT

基于JWTToken认证机制实现

JSON Web TokenJWT)是一个非常轻巧的规范。

这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息,

restful api的无状态认证

 

JWT的组成

一个JWT实际上就是一个字符串,它由三部分组成,它们之间用圆点(.)连接

分别是:

Header     声明类型以及加密算法

Payload    存放有效信息的地方  过期时间 ….

Signature  签证信息

 

token示例:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJOYW1lIjoibGFtcG9sIiwiZXhwIjoxNjQyNDA5ODExLCJpYXQiOjE2NDI0MDk3NTEsInN1YiI6InVzZXIgdG9rZW4ifQ.knArw6dhbVwWMkiMzgQ3JWymFl_HU5c4-nwanO72xE8

 

Header   jwt的头部由两部分信息组成:

type:声明类型,这里是jwt

alg:声明加密的算法 通常直接使用 HMAC SHA256

{

"type":"jwt",

"alg":"HS256"

}

安装JWT

go  get -u  github.com/dgrijalva/jwt-go

 

jwt生成token字符串

 

生成token代码如下:

 

type UserClaims struct {
    jwt.StandardClaims //嵌套
    UserName           string
}

var JWTKEY = []byte("asdfadsfadsf")  //签名的key,任意填写即可
// 获取token
func getToken(c *gin.Context) {
    //payload
    claims := UserClaims{
        UserName: "lampol",
        StandardClaims: jwt.StandardClaims{
            ExpiresAt: time.Now().Add(60 * time.Second).Unix(), //过期时间
            IssuedAt:  time.Now().Unix(),                   //签发时间
            Subject:   "user token",
        },
    }
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, &claims)
    tokenString, err := token.SignedString(JWTKEY)
    if err != nil {

        log.Fatal(err.Error())
    }
    c.JSON(http.StatusOK, gin.H{
        "code":  200,
        "msg":   "get token success",
        "token": tokenString,
    })

}
func main() {
    router := gin.Default()
    //定义路由
    router.GET("getToken", getToken)
    router.Run()
}

 

运行:http://localhost:8080/getToken 得到如下结果

{"code":200,"
msg":"get token success",
"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2Nzk3Mzc4OTcsImlhdCI6MTY3OTczNzgzNywic3ViIjoidXNlciB0b2tlbiIsIlVzZXJOYW1lIjoieWFuZ3BocCJ9.c7ZA1SGiZSnocFF5Y7M_kRugqJy3xsIAl3Jjcv9Axgk"}

 

 

 

token过期说明:

jwttoken生成出来后,过期时间未到是不会过期的。如果需要在程序中设置过期,就需要在将token加入数据库或者redis中,将对应token的值设置为过期即可

项目中:

先使用jwt进行token验证

然后再使用数据库或者redis再进行验证一次

全部通过后才可以正常使用

token解析验证

 

type User struct {
    Token string `form:"token" binding:"required"`
}
// 解析token
func ParseToken(c *gin.Context) {
    var u User
    err := c.ShouldBind(&u)
    if err != nil {
        c.String(http.StatusOK, err.Error())
        return
    }
    claims := UserClaims{}
    token, err := jwt.ParseWithClaims(u.Token, &claims, func(t *jwt.Token) (interface{}, error) {
        return JWTKEY, nil
    })
    //解析错误
    if err != nil{
        c.JSON(http.StatusOK, gin.H{"code": 404, "msg": "token invalid"})
    return
    }
    //验证失败
    if token.Valid != true {

        ve, _ := err.(*jwt.ValidationError)
        if ve.Errors == jwt.ValidationErrorExpired {
            c.JSON(http.StatusOK, gin.H{"code": 404, "msg": "token expired"})
        } else {
            c.JSON(http.StatusOK, gin.H{"code": 405, "msg": "token invalid"})
        }
        return
    }
    //验证成功,
    c.JSON(http.StatusOK, gin.H{
        "code" : 200,
        "msg" : "token valid success",
        "token": token,
    })
    return
}

func main() {
    router := gin.Default()
    //定义路由
    router.GET("getToken", getToken)
    router.GET("ParseToken", ParseToken)
    router.Run()
}

 

完结