Golang 使用 JWT 跨域鉴权 | 青训营笔记

365 阅读2分钟

Golang 使用 JWT 跨域鉴权

这是我参与「第三届青训营 -后端场」笔记创作活动的第3篇笔记。

01 简介

JWT全称 JSON Web Token是一种跨域认证解决方案,属于一个开放的标准,它规定了一种Token实现方式,目前多用于前后端分离项目和OAuth2.0业务场景下。

本次案例以极简版抖音项目为例,大致介绍下使用方法。

02 步骤

1、安装 jwt

 go get github.com/dgrijalva/jwt-go

2、生成 jwt

这个字段可以根据自己的需求自行添加、修改。

 // MyClaims 自定义声明结构体并内嵌 jwt.StandardClaims
 type MyClaims struct {
     Username string `json:"username"`
     Password string `json:"password"`
     jwt.StandardClaims
 }

这里定义了一个秘钥 MySecret ,通过调用 func GenToken(username string, password string) (string, error) 函数使用指定的 MySecret 签名并获得完整的编码后的字符串 token ,这里的返回值就是字符串 token 。

ExpiresAt:过期时间,time.Now().Add(time.Hour * 24).Unix() ,即获取当前时间并加上自定义的的时间,最后通过 Unix() 转换成时间戳。

Issuer:签发人,可以自定义。

 // MySecret 定义Secret
 var MySecret = []byte("douCheng")
 ​
 // GenToken 生成JWT
 func GenToken(username string, password string) (string, error) {
     // 创建一个我们自己的声明
     c := MyClaims{
         username, // 自定义字段
         password,
         jwt.StandardClaims{
             ExpiresAt: time.Now().Add(time.Hour * 24).Unix(),               // 过期时间
             Issuer:    "douCheng",                                          // 签发人
         },
     }
     // 使用指定的签名方法创建签名对象
     token := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
     // 使用指定的secret签名并获得完整的编码后的字符串token
     return token.SignedString(MySecret)
 }
 ​

3、解析 jwt

ParseToken 函数:解析字符串 token ,返回对应的刚刚自定义的结构体数据 MyClaims

主要使用 jwt.ParseWithClaims()

 // ParseToken 解析JWT
 func ParseToken(tokenString string) (*MyClaims, error) {
     // 解析token
     token, err := jwt.ParseWithClaims(tokenString, &MyClaims{},
         func(token *jwt.Token) (i interface{}, err error) {
             return MySecret, nil
         })
     if err != nil {
         return nil, err
     }
     if claims, ok := token.Claims.(*MyClaims); ok && token.Valid { // 校验token
         return claims, nil
     }
     return nil, errors.New("invalid token")
 }

4、验证 token

几乎每个的功能实现都需要验证 token ,如果都调用 ParseToken然后去验证一次未免也太繁琐了,所以这里写一个 TokenIsValid 的函数,每次想验证只调用这一个并返回响应的 model 的结构体数据就好了。这里拿到 claims.username 之后,通过调用数据库查询相应的 model.Userinfo 。

 func TokenIsValid(token string) (model.Userinfo, bool) {
     var userinfo model.Userinfo
 ​
     // 是否过期
     claims, err := ParseToken(token)
     if err != nil {
         return userinfo, false
     }
 ​
     // 拿到 claims.username 之后,通过调用数据库查询相应的 model.Userinfo
     user, err := dao.Mgr.IsExist(claims.Username)
     if err != nil {
         log.Println(err)
         return userinfo, false
     }
 ​
     if user.Name != claims.Username {
         return userinfo, false
     }
 ​
     return user, true
 }

03 总结

开头介绍了什么是 JWT、怎么安装 jwt-go 库。然后通过生成 token 和解析 token 、具体验证实例,介绍了大致的过程方法。jwt-go 不仅限于这些,大家可以阅读官方文档进一步了解。

参考资料:

github.com/dgrijalva/j…