JWT 身份认证模式
基于session 的方式存在的问题
-
服务器端需要存储
session,并且由于Session需要经常快速查找,所以通常存储在内存中,或者内存数据库中。如果同时又大量用户在线,就会占用大量的服务器资源 -
当需要扩展时候,创建
session的服务器可能不是验证session的服务器,所以还需要将所有session单独存储并共享,后来又有人想到,把所有的seesionid放到同一台电脑上,让所有的用户都访问这同一台电脑,但是如果那个存储sessionid的服务器挂掉了,那就要让所有的用户都得重登。 -
由于客户端使用
cookie储存SessionID, 在跨域场景下需要进行兼容性处理,同时这些方法也难以方法CSRF攻击
Token 认证模式
基于 session 存在的这些问题,所有就有人在想,凭什么让我去保存这些该死的 sessionId,让用户自己存就好了,那么当用户把 认证信息传过来的时候,我怎么判断这个是我颁发的,还是他自己伪造的?这其实就变成了一个验证的问题。
Token 的流程
- 服务端使用用户名、密码进行认证
- 服务端验证用户名、密码正确以后,生成
Token返回给客户端 - 客户端保存
Token,访问需要认证的接口时,在 url 参数或HTTP Header中加入Token - 客户端通过解码
Token进行鉴权,返回给客户端需要的数据
Token 的优势
可扩张性
在客户端存储的Tokens是无状态的,并且能够被扩展。基于这种无状态和不存储Session信息,负载负载均衡器能够将用户信息从一个服务传到其他服务器上。
安全性
请求中发送token而不再是发送cookie能够防止CSRF(跨站请求伪造)。即使在客户端使用cookie存储token,cookie也仅仅是一个存储机制而不是用于认证。不将信息存储在Session中,让我们少了对session操作。
token是有时效的,一段时间之后用户需要重新验证。我们也不一定需要等到token自动失效,token有撤回的操作,通过token revocataion可以使一个特定的token或是一组有相同认证的token无效。
可扩展性
使用tokens时,可以提供可选的权限给第三方应用程序。当用户想让另一个应用程序访问它们的数据,我们可以通过建立自己的API,得出特殊权限的tokens。
Refresh Token
通常 access token 的有效期会比较短(一般10分钟),refresh token,的时间比较长(比如 7 天),当用户的 access token 过期的时候,可以使用 refresh token 来动态刷新 access token ,如果 refresh token 也过期了,那么用户就只能重新登录了。
JWT 引入 Refresh Token 以后的工作流程
-
用户使用用户名字和密码进行登录
-
服务器端生成有效期较短的
Access Token,和有效期较长的refresh token -
访问接口的时候,携带的是
Access Token -
如果
Access Token过期了,则用户就会使用refresh token向刷新接口请求新的access token -
如果
refresh token也过期了,那么只能重新登录了
JWT 的劣势
在实际的生产环境中,使用 jwt逻辑进行鉴权的,其实比较少(最起码,我遇到过的项目,基本没有用的)。这主要是因为使用 jwt 配置较为复杂,且每次通信,都要进行解密token,比较消耗性能。至于其扩展性,现在完全可以在集群内创建一个公用的 redis存储 sessionId,就可以实现集群内的服务共享,且只要鉴权的这个服务没挂,就没事。
浙公网安备 33010602011771号