即用户登录后,客户端得到JWT,此后不断刷新或是过期后刷新token。
这个方案利用得十分广泛,险些成了事实标准。但并不屈安,有以下几个问题:
1,JWT 密钥管理问题

JWT 的安全的基石是担保秘钥(secret key)的安全,由于一旦秘钥透露,拥有秘钥的人可以假造所有用户。这给管理带来了麻烦,我们还要完备信赖管理职员,管理职员变动就要修正秘钥,而修正秘钥又会打断用户的登录状态。大概有人会说,这不是问题,这个和数据库账号密码管理一样啊,这个还有些不同,生产环境的数据库账号密码常日会有登录IP限定。
2,JWT 无法注销的问题
当用户修正密码后,常日须要注销之前颁发的token,为了实现这个功能须要引入token的集中储存和检讨,这毁坏了JWT分布式的优点。
3,JWT 的刷新机制有问题。
为了安全,很多人都知道token长期保持不变不屈安,常日会采纳刷新token的机制。当是当下,很多刷新机制是为了刷新而刷新,常见的token刷新机制是:到期后刷新,或是提前刷新,或者定时刷新。如果token被盗,黑客和合法用户都可以通过刷新来获取新的token,这并没带来实际的安全提升。
二 问题解答1,针对JWT秘钥管理问题
这里给出的方案便是不该用JWT, 采取一个类似session 的机制,利用一个随机值(uuid)做token, 用户数据在后台集中的redis存储和查询。暂且称之为UUID Redis Token.
JWT的最大有点便是自身可存储用户数据,不用到集中的存储点查询,便于分布式运用,这个特点导致了已发布的JWT无法撤销。现实中,很多利用JWT的公司并不是纯挚的在jwt里取用户数据,依旧在集中的做事器取数据。还有,对付像图片,视频等须要用户登录的检讨,常日把token放到url 里,而JWT显得数据过大。
利用redis在后端保存用户信息有良好的扩展性,足够应知足大型网站的需求。
这个的uuid 并不哀求按标准格式,只需不重复即可,对付PHP 很随意马虎天生:
$token = bin2hex(random_bytes(20));不要嫌这一行代码过于大略,对付地球上的公司,这已经足够安全了。
讲到这里,这个机制和传统的session 机制是类似的,uuid 相称于session-id,不同的地方是传统session客户端一定韶光(常日为20分钟)不生动就自动退出,我们须要做些改进,知足手机APP长期上岸的需求。
2,改进方案(UUID Redis Token)的特点
为了表述方便,以下假设手机APP哀求90天内保持上岸,token超过2小时就刷新每个token有一个较长的有效期,比如90天,这个是为了知足长期登录的需求;每个token有一个较短的刷新间隔,比如2个小时。常常改换token 提升安全性;每当token刷新时,创建并颁发新的token,同时修正旧的token的有效期,比如60秒后过期,担保旧的token快速到期同时又短暂可用,(并发要求时,可能会用到旧token)每当用户重新登录或是修正密码,删除token。刷新token时,利用redis或mysql 的锁机制,确保并发要求时只有个要求刷到新的token。做事器token处理逻辑:通过token在redis里获取用户数据,如果找不到则表示token失落效或缺点,哀求用户再次登录。如果找到用户信息且token 是2个小时内创建的,则不刷新token, 如果token创建韶光超过2个小时前,则创建新的token给用户,做事器复制用户数据到新的token,同时修正旧token 60秒后过期。此方案,多数情形下只是对redis的读写操作,性能极高,在刷新token时,须要用到redis或MySQL的锁机制防止并发刷新,确保同一客户端一次刷新只有一个要求刷到新的token,由于刷新token操作间隔的韶光较长,不是高频操作,对性能也影响不大,合营redis集群,足够应对海量用户。