什么是JWT(Json Web Token)
用户认证是计算机安全领域一个永恒的热点话题.
JWT 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519)。
该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。
JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,该token也可直接被用于认证,也可被加密。
传统的session认证
我们知道,http协议本身是一种无状态的协议,而这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证,那么下一次请求时,用户还要再一次进行用户认证才行,因为根据http协议,我们并不能知道是哪个用户发出的请求,所以为了让我们的应用能识别是哪个用户发出的请求,我们只能在服务器存储一份用户登录的信息,这份登录信息会在响应时传递给浏览器,告诉其保存为cookie,以便下次请求时发送给我们的应用,这样我们的应用就能识别请求来自哪个用户了,这就是传统的基于session认证。
传统的session认证方式对于单机单端应用非常方便。
但是这种基于session的认证使应用本身很难得到扩展,随着手机、电视等多种客户端(多端)的出现,独立的服务器已无法承载更多的用户,而这时候基于session认证应用的问题就会暴露出来
session的缺点
如果是分布式应用前后端分离,那么原来的cookies或者session在使用上就会有很大的问题
cookie和session认证需要在同一主域名下才可以进行认证
如果用户量很大,服务器需要不停的跟新会话,会造成服务器响应变慢
针对以上两种问题,目前可以把session存储在redis内进行解决 ,但并不是最终的解决办法
什么Token(令牌)
我们需要一种机制,每个请求中,可以在请求header头中带上一串密钥,这个密钥就是通行证
而这个密钥的合法性和有效性有服务端来控制,那么我们的服务端只需鉴定这个密钥是不是授权的真实密钥
无需保存session文件信息,这个密钥就是token,翻译过来叫令牌 。
JWT就是这样一种机制
流程上是这样的:
-
用户使用用户名密码来请求服务器
-
服务器进行验证用户的信息
-
服务器通过验证发送给用户一个token
-
客户端存储token,并在每次请求时附送上这个token值
-
服务端验证token值,并返回数据
这个token必须要在每次请求时传递给服务端,它应该保存在请求头里
另外,服务端要支持CORS(跨域源资源共享)策略
一般我们在服务端这么做就可以了Access-Control-Allow-Origin: *
JWT的结构
一个jwt字符串由三部分组成,用.
号分隔。
第一部分:头部(header)
{
"alg": "HS256", //加密类型
"typ": "JWT"
}
然后,这个json被Base64Url编码,成为第一部分
第二部分:载荷(payload)
{
"sub": "1234567890",
"name": "John Doe",
"admin": true //这部分是消息内容
}
然后,将有效载荷Base64Url进行编码,成为第二部分
第三部分:签证(signature)
使用编码后的第一部分,编码后的第二部分,然后一个用于加密的密钥secret。
采用第一部分里的加密算法进行签名
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
最后生成一个这样的字符串
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.wqt1_0iXaZCLjlpivjacftb4O1xRo8QE08Z2x1jziMw
JWT的缺点
1. 无法作废已颁布的令牌(对token刷新使用期限)
2. 不易应对过期数据(支持 token 失效)
3. 如果密钥过于简单,很可能会造成cookie伪造漏洞
所以如果你使用了 token ,那么如果 token 被捕获到,那么就可以进行伪造进行冒充。所以如果安全比较高的话,还是建议使用oauth2