JWT,java web token,由头部+载荷+签名三部分组成,其中头部和载荷仅使用了base64进行编码,所以载荷尽量不要传递一些敏感信息(比如:密码之类的)。签名主要是用于验签,防止载荷被抓包篡改。
这里直接切入主题!
续签:jwt token都有一个有效期,要有一个机制可以让一直操作的jwt token进行续签。
这里采用长短token进行续签,短token用于业务请求,长token用于刷新token。
大概方案是:
步骤1:用户未登录,跳转到登录页。
步骤2:用户输入正确的用户名和密码,登录成功,然后生成2个jwt token,两者只是时间有效期不一样(一般是30分钟、1小时,其中载荷包含自定义字段用户ID、随机字符串、客户端IP),然后根据用户ID+字符串进行md5编码生成有状态的token,后端存储2个redis值,返回长短token到前端。
后端存储2个redis key:
一是以有状态的token为key,值没有意义(可随便定义),有效期和长token一致,主要用于校验token的有效期,。
二是以userId为key,值为map[field为设备,value为有状态的token],未配置有效期,主要是用于查看在线用户数据以及用户登录设备控制。
步骤3:用户请求接口,传输短token请求业务,一是校验token的合法性,二是比对token的请求ip地址是否和jwt的一致,三是校验是否jwt是否过期,四是校验有状态的token是否存在,都通过的话正常请求,未通过的话走步骤4。
其中,校验请求客户端IP,主要是防止短token的抓包窃取,这样就能保证安全性。至于网络切换导致ip地址变动,则可以通过长token重新获取。
步骤4:用户根据返回的未授权响应码,传输长token进行刷新token操作,一是校验token的合法性,二是校验有状态的token是否存在,不存在的话提示需要重新登录;存在的话刷新token,返回长短token到前端,然后同步删除有状态的token,redis重新保存一份有状态的token,以及userId token值根据设备更新或新增。
相关问题:
token刷新的并发问题,可以从2个方面来控制:
一是前端控制,第一次拦截到未授权响应码,进行刷新token操作,并设置一个开关,在请求刷新token的过程中,其他请求过来则进行缓存,待到刷新token成功后重新执行。
二是后端控制,在第一次校验发现token过期时,重新生成一份新的token并使用redis分布式锁控制,在生成的同时缓存一个短时间的token(一般为30s)用于过渡处理。但此种方案只适用于长token缓存于服务端的情况。