GOLANG:jwt的使用

354 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

jwt的特点

简洁,不占用服务端存。

cookie和session

http协议无状态的,每次请求对于服务端来说都是一个独立的,早期保存用户信息使用的是cookiesessioncookie存储在客户端,存一个sessionid每次请求时携带上,session存储在后端,每次通过请求携带过来的sessionId去找对应的session数据,判断用户信息。

这种方式存在一些弊端,session是基于cookie的。cookie不支持跨域\用户禁用cookie时\用户使用的是移动设备,一但cookie无法使用,那么session也会无法使用。

token

token的出现解决了这一问题,他将鉴权信息放在请求头部,在http头部拿到信息后进行用户验证,这就解决了cookie无法使用时的验证用户信息的问题

jwt

jwt是对token的进一步改造。它与token相比, token数据存在服务端, jwt存储在客户端。jwt不会占用服务器资源,但是他会消耗cpu的处理(与token相比)

jwt 的组成

jwt由头部(head)、用户信息(claim)、签名(signal)三个部分通过.拼接后再用base64编码成的一段字符串。

jwt的交互过程

  1. jwt的获取

    客户端发送身份信息到服务端,服务端校验完成后将部分用户信息加密,生成一个jwt字符串给客户端。客户端获得一个jwt字符串。

getjwt.png 2. 业务请求中携带上jwt

获取到jwt字符串后,每次请求都携带上它,用于标识身份。

auth.png

jwt在服务端的验证过程

服务端获取到jwt字符串后,

  1. 先将字符base64解码,拆分成三部分:headclaimsign
  2. head中存放了sign的加密方式,通过将cliam与服务端的密钥(secret)通过head中的加密方式加密,生成一个sign2
  3. sign2与客户端的sign比较(sign2 == sign ?),如果一致说明是签发的jwt。不一致则说明发送的字符串有问题
  4. 再检验jwt的时效,是否过期 check.png

在golang使用

命令行下安装jwt模块

go get github.com/golang-jwt/jwt/v4

生成jwt

  1. 声明claim,存储用户信息jwt信息

  2. 生成token对象

  3. 使用token对象的SignedString方法生成最终的token字符串 jwt-init.png

// 略... 
// 创建 Claims ,MyCliams是自定义的jwt结构体
claims := &MyCliams{
    params.Name,
    params.Age,
    jwt.RegisteredClaims{
        ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 24)), // 过期时间
        Issuer:    "",                                                 // 签发人
    },
}
// 生成token对象
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// 生成签名字符串
tokenstr, err := token.SignedString(secret)
// 略... 

验证jwt

// 略... 
/**
@ params.Token 是客户端发送过来的token字符串
@ &claim 是存放结果的结构体
*/ 
token, err := jwt.ParseWithClaims(params.Token, &claim, func(token *jwt.Token) (i interface{}, err error) {
		// secret 是服务端加密使用的密钥,生成时也是用这把
		return secret, nil
})
// 返回的是接口,将它断言为自定义结构体指针
cl, ok := token.Claims.(*MyCliams);
// 略... 

code.png

客户端重复申请jwt问题

客户端一直访问登录接口,服务端因为没有记录,无法判断用户是否登录过。

总结

jwt是随着不同业务需要,演化而来。相比于cookie和token,jwt并不占用服务器存储,切安全,能够支持单点登录。但也是它不占用服务器资源的有点,导致它对jwt的控制不完整,他只能颁发而无法主动销毁,除非在服务端存下记录。