zoukankan      html  css  js  c++  java
  • JWT实战总结

    公司的登录模块也从Session切换到JWT挺长一段时间了,抽时间来总结一下遇到的问题以及解决方案.

    图片

    为什么用JWT?

    在JWT之前,公司是利用传统的Session来实现登录状态的保持,分布式下则利用Redis实现Session共享集中管理,共享集中管理会带来登录强依赖Redis,然而公司的Redis确实不太稳定,导致一蹦或者网络抖动就会使得用户受到影响,另外一点就是用户的Session存在redis中没有设置超时时间,其格式为 UUID - 用户信息JSON串,这个是大坑,导致Redis等我接手时已经膨胀到了30G之多,因此在大家强烈要求下JWT的改造就此开始.
    之所以选择JWT,因为其不需要服务端存储,也就是可以直接下掉Redis,另外其playload可以存储不少关键信息并且小巧接入成本极小.

    会有哪些问题?

    Token中存哪些必要东西?

    Jwt Token的playload实际上只是base64编码了一层,其被解码后可以查看到具体的文本信息,因此不能存私密性的东西.建议存储 id,username,expire,version等一些不是很关键的数据.至于version有什么用,后面吊销的时候在讨论.

    Token何时下发?

    1. 登录下发新token,原token实际上并没有失效,保证多端登录没问题.

    2. Token剩余有效时长大于可续期时长(根据业务平台自己定)时重新下发.举个栗子针对WEB端Token24小时有效,当有效时间小于12小时刷新Token,也就是当用户连续12小时没操作网站才会被退出.

    3. 修改或者重置密码时下发新Token,并吊销之前的Token

    Token如何吊销?

    JWT不需要在服务端存储,因此吊销是个大问题,无法吊销的话就会出现用户密码被盗,即使用户修改了密码,其他人也并不会立即失效,这点在安全性很高的地方几乎是不允许的情况.因此吊销是必要的.
    吊销方案有存储黑名单Token,个人觉得不是很好,一长串的东西扔哪都不合适啊,因此想着存储用户的version在Token中,当用户修改或重置密码后期版本自增,那么当请求到来时与Token中version进行对比,不一致则直接拒绝访问,实现了吊销.
    缺点也很明显每次请求到来都需要去DB或者缓存取出用户的版本,然后与Token中的version进行一次判断,这个看业务容忍度来取舍了.个人建议放Redis的中,即使1000w数据内存占用也是非常少的,而且对于大多数业务来说这个并不需要强依赖,Redis挂了则根据异常以及Token的到期时间自由选择直接放行还是拒绝.

    Token签名秘钥如何替换

    Token为了保证其可靠性,因此必须有签名串并且还需要HTTPS防止中间人攻击,因此秘钥更换也是必须的.
    所采取的方案是用一个定长为2的secret[2]数组来保存秘钥,秘钥是存储在配置中,下发时使用secret[0],验签时也从secret[0]开始验签,验签失败则使用secret[1]验签,当然为了加快替换流程,secret[1]验签成功后需要重新下发secret[0]签名的Token,在运行一段时间后则可以把secret[0]替换为secret[1],重新增加新秘钥放入secret[0]中.因为秘钥都是写在配置中的,因此每次只需要重新发下配置即可.

    如何与现有结构兼容?

    兼容实际上判断有没有下发Token,没有则使用原本Session的验证,在验证成功后下发Token,保证下次请求可以使用Token验证,那么这样跑一段时间则能保证绝大部分活跃用户切换到了Token流程.
    图片

    旧Redis如何清理?

    旧Redis中存储着大量key为UUID并且没有失效时间的字符串,清理只能扫描所有的key,然后判断是不是UUID的格式,判断是否有失效时间,没有则删除.那么会有以下问题

    列出所有Key

    1. KEYS 生产上禁止使用的命令,其复杂度是O(N)也就是全遍历,会带来性能问题.

    2. SCAN迭代模式, SCAN每次返回一定量的key集合,并且返回下次迭代的游标,是可以在生产环境上使用的命令,因此最佳选择.

    清理操作

    清理脚本就很简单的扫描出key,判断是否为UUID格式,然后利用TTL命令判断是否设置过期时间,没设置则删除.注意该清理要在Token替换了大部分Session之后进行,保证对当前使用Session的用户无太大影响

  • 相关阅读:
    [转]MySql 5.7关键字和保留字-附表
    [转]超链接标签简单的几个样式属性
    layui table 前台数字格式保留两位小数,不足补0(mysql 数据库)
    [转]Object.keys()和for in的排序问题
    [转]对form:input标签中的数字进行格式化
    [转]bootstrap table 动态列数
    [转]bootstrap的table插件动态加载表头
    [转]【MyBatis】Decimal映射到实体类出现科学计数法问题
    [转]MySQL函数大全 及用法示例
    [转]mysql update case when和where之间的注意事项
  • 原文地址:https://www.cnblogs.com/lanblogs/p/15161775.html
Copyright © 2011-2022 走看看