JWT
传统的session认证
http协议无状态,浏览器和服务器之间,为了识别是哪个用户,需要在服务器端存储用户登录的信息,并通过cookie记录在浏览器,每次请求时,通过cookie来识别是哪个用户。
存在的问题
-
存储:用户经过认证,服务端要记录用户信息,以便下次请求的鉴别,随着用户增加,内存消耗增加
-
扩展:只在单机内存中记录,粘性session才能正确处理用户识别,分布式环境下,扩展能力受限。
-
CSRF:基于cookie传递来识别身份,如果cookie被截取,很容易收到跨站请求伪造的攻击。
基于token的鉴权机制
类似于http协议,也是无状态的,不考虑在服务端保留用户的认证信息或者会话信息。不需要考虑用户在哪一台服务器登陆过,为扩展性提供了遍历。
基本流程:
用户使用用户名密码登录 => 服务器验证 => 验证通过发给用户一个token =>
客户端存储token并在每次请求时携带 => 服务端验证token有效性并返回数据
token一般保存在请求头里。
JWT
JSON Web Token - 在Web应用间安全地传递信息
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
var signature = HMACSHA256(encodedString, 'secret');
var jwt_token = encodedString + '.' + signature
JWT由服务器签发和生成,并且有服务器来校验
校验的方式,是通过header和payload的内容,重新按规则计算jwt_token,比较用户传来的token和计算的token是否一致即可。
所以加密用的私钥secret就很重要,不能流露出去。否则谁都可以伪造生成合法的token了。
当验证token正确之后,就可以读取payload里的信息,确认用户身份真实且知道是哪个用户(payload里需要有用户信息),返回请求数据了。
优点
-
json格式,跨语言都可以很好的支持
-
payload里可以存储一些非敏感信息,可以携带一些额外信息
-
传输压力小
-
因为存在于客户端,服务端只做签发和校验,不用保存,服务端可以任意扩展
安全
-
payload是base64编码,可逆向解析,不应该存放敏感信息
-
保护好secret
-
使用https
理解
session存储在服务端,用户多会造成服务器存储资源消耗大,不论是用本地内存还是分布式缓存。
token存储在客户端,服务器只做验证处理,每次都要验证,会消耗服务器计算资源。
所以token是用时间换了空间的思路。
并且还有一个缺点,由于token发出后,就无法回收,所以无法做主动登出,只能等token过期。虽然可以通过减少过期时间,自动续期等方式来解决,但是无法实现实时主动登出。如果还在服务端记录token过期时间,相当 于又回到了服务端存储的老路子了。