jwt与token+redis,哪种方案更好用?
jwt与token+redis,哪种方案更好用?
-----
网友解答:
-----
其实在生产中,两者都离不开。jwt的优缺点很明显,优点是无状态,无需存储。因此对分布式应用来说,性能好。加上可以携带部分负载,省了许多的数据库连接。但由于他的不可撤销,很容易被人用来重放攻击。因此在生产中,jwt主要用于身份验证,以及携带部分非隐私性的数据。如果在进行如资金操作之类安全性要求较高的场景时,通常会使用验证码等二次密码手段,以redis加token进行更进一步的检验。两者是要相互结合的。当然对一些一般的应用jwt足够了
-----
网友解答:
-----
1. 问题描述
jwt与token+redis,哪种方案更好用?
问题结论
刚好最近有项目使用了jwt,而且是定制化的jwt的认证机制,就个人的理解而言,各自有其优缺点,并且针对不同的场景需要进行约束性开发,如用户剔除、同一用户每2h只生成一次jwt等。
2. Token机制简述
2.1 Token的用途
用户在登录APP时,APP端会发送加密的用户名和密码到服务器,服务器验证用户名和密码,如果验证成功,就会生成相应位数的字符产作为token存储到服务器中,并且将该token返回给APP端。以后APP再次请求时,凡是需要验证的地方都要带上该token,然后服务器端验证token,成功返回所需要的结果,失败返回错误信息,让用户重新登录。其中,服务器上会给token设置一个有效期,每次APP请求的时候都验证token和有效期。在存储的时候把token进行对称加密存储,用到的时候再解密。文章最开始提到的签名sign:将请求URL、时间戳、token三者合并,通过算法进行加密处理。
2.2 token+redis机制
用户验证通过后,服务端通过如uuid相关的方法,生成token,存储用户信息。当请求服务时,客户端将token带上来,进行查询验证,如token存在并在有限期内,请求有效,否则请求非法。token + redis机制是中心化的,每次验证token有效性时,都需要访问redis,其核心优点实服务端可以主动让token失效,缺点是每次都要进行redis查询。占用redis存储空间。
2.3 jwt机制
这是一种无状态身份验证机制,因为用户状态永远不会保存在服务器内存中。 服务器受保护的路由将在授权头中检查有效的JWT,如果存在,则允许用户访问受保护的资源。 由于JWT是独立的,所有必要的信息都在那里,减少了多次查询数据库的需求。
Java jwt普遍选用java-jwt工具包依赖,gradle依赖:compile 'com.auth0:java-jwt:3.2.0'用户发起登录请求,验证通过后,服务端创建一个加密后的JWT信息,作为Token返回。在后续请求中JWT信息作为请求头,发给服务端。服务端拿到JWT之后进行解密,正确解密表示此次请求合法,验证通过;解密失败说明Token无效或者已过期。jwt的有点主要有:a.其是去中心化的,便于分布式系统使用; 2. 基本信息可以直接放在token中。 user_id,session_id; 3. 功能权限信息可以直接放在token中。用bit位表示用户所具有的功能权限。 其缺点有:服务端无法主动让token失效,另一个是无法很好的控制payload的数据量。
3. 小结
jwt和token+redis两种方案,没有最优,只有结合不同的业务场景,需求最适合的方案。就比如token 2h过期,同一用户每1.5h只生成一次token,当两次token并存时,同时有效。大家可以考虑在这两种方案的前提下,分别如何实现?
作者:夕阳雨晴,欢迎关注我的头条号:偶尔美文,主流Java,为你讲述不一样的码农生活。
-----
网友解答:
-----
两种方式的优缺点你在问题中说的很清晰,适用的系统根据实际场景我觉得不难分析。以下为我自己的一些思考。
在拥有庞大用户量的系统中,用户保持登录态仅作为跟踪分析用户行为,不会对账户本身造成过大影响。那么我认为它的登录剔除操作不重要,我也不允许它不断的为校验用户来刷我的库甚至redis,用jwt很合适。
预警系统对行为上报异常账户进行监测,只监测一批异常用户,我需要知道它的实时状态,随时准备token失效,那么token+redis就有必要了。
一般的通用系统,我推荐的采用jwt+redis的组合方案。jwt进行认证,redis作为证书撤销列表(CRL)来使用,也就是黑名单。
从通用系统出发,认证是个频繁操作,几乎每次的请求都需要获取登录认证数据,在令牌有效范围内进行拉黑,这样的令牌正常跟用户量来比较,为数不多。
具体认证方案步骤如下:
step1:用户登录,验证通过,由认证服务器jwt方式签发token,时效30分钟。
step2:用户行为,jwt验证通过,CRL中token不存在,向后执行coding…
step3:发现用户异常,用户token写入CRL,时效30分钟。这样可以保证签发的token可以在有效期内一直被拉黑。
step4:用户行为,jwt通过,CRL不通过,重新登陆或者其他业务逻辑。
对比单纯jwt方式,组合方案会多出一次redis请求,这样对分布式的登录验证有一定的破坏,增加了一次网络开销,需要根据业务预计的黑名单换入换出频率和黑名单总容量来评估使用这种方案是否合适。
对比单纯token+redis方式,组合方案用一次jwt摘要算法(通常一次本地SHA256)来替换一次查库校验,信息的实时性不强,不是每次获取最新信息,但是速度会快,用本地的一次计算减少最少一次网络IO,数据查询,给数据库的压力也会大减,注意保存好私钥。
解决方案可以多种多样,我们也可以从其他方向寻找灵感,例如OAuth2,PKI/CA 体系证书的验证。一个实现方案+配套系统的配合就可以打造出想要的效果。
欢迎随时讨论。
-----
网友解答:
-----
为什么不用jwt+redis?
思路其实和token那个差不多
生成时把两个token(访问token和刷新token)都存redis,刷新过后把之前的访问token丢redis的黑名单里,生成的时候刷新token还在有效期内就生成一个访问token。
举例子:
访问只能用访问token,时间假设30分钟,刷新token假设30天,只能用于重新获取访问token。
第一次访问:
获取两个token,并存入redis中。
第二次访问:
只使用访问token,当访问token有效时间在1分钟以内时,刷新token,获取一个新的token,刷新时把老访问token丢黑名单,时效一分钟。
修改密码退出登录等:
同理检查黑名单,在黑名单里直接就不解析token是否有效,直接返回无效token就行。只要刷新就把以前的token丢黑名单,刷新时,刷新token作为访问接口的token,老token作为传递的凭证,防止疯狂刷新导致你的redis黑名单无限增长。
这样有一个好处,你不用频繁的访问数据库来判断token是否有效,只需要计算jwt是否有效和配合redis来维护有效的token
-----
网友解答:
-----
各有各的优缺点,我个人更倾向于jwt,因为我更多参与的是比较小的项目,公司技术开发的资金有限,再说也没有人会攻击,因为不入黑客的眼睛,而且就算攻击,99%不能够直接破解你的jwt加密技术,最多获取到别人的jwt去伪造别人的用户操作,能做到这步也不容易,再加上我们的用户更少,token+redis其实对于我们也是一样的,因为流量不大,服务器的开销也不大,但相比jwt更方便,也不用担心redis服务挂了。
------------------
推荐阅读: