什么是JWT?javascript
Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登陆(SSO)场景。JWT的声明通常被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也能够增长一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。html
JWT最广泛的一个做用就是用来保存用户的登陆信息。html5
之前都用session保存用户的登陆信息,为何如今又须要用JWT呢?java
先回顾一下基于session保存用户的登陆信息的原理:web
session的数据通常存储在redis上,储存的格式通常是这样:redis
因此,session有什么缺点呢?算法
- 这种模式最大的问题是,没有分布式架构,没法支持横向扩展。若是使用一个服务器,该模式彻底没有问题。可是,若是它是服务器集群或分布式结构的话,则须要一个统一的session数据库库来保存会话数据实现共享,这样负载均衡下的每一个服务器才能够正确的验证用户身份。
- sessionid储存在cookies上面的,因此也要作CSRF防御。cookie若是被截获,用户就会很容易受到跨站请求伪造的攻击。
- 单点登陆问题:难以适用于单点登陆(Single Sign On : 简写SSO)的场景
- 移动开发通常都不使用sessionid来保存登陆状态
附:数据库
什么是单点登陆(SSO)?安全
单点登陆就是登陆一次,能够访问多个不一样的子系统(不一样的域名)。当你登陆了淘宝以后,打开天猫后就自动登陆,即便淘宝和天猫是不一样的域名。若是没有单点登陆的话,你登陆了淘宝,再登陆天猫,也是须要输入帐号密码登陆的。服务器
JWT的优势就是能解决上面session的缺点......最重要的是能有效地解决单点登陆问题。
流程:
1)用户登陆成功后,服务器签发jwt,里面储存着用户的id等资料,用于标记用户的登陆状态。注意!不能保存敏感信息,例如密码这些,具体缘由下面有说。
2)而后在响应报文传送回去给客户端。
3)客户端收到以后,经过html5的 localStorage 或 sessionStorage 来保存JWT。
4)在下一次访问的时候,经过请求头把JWT带上,服务端收到以后,会进行校验,校验有没有修改过啊,有没有过时啊等。
5)校验经过以后,就能够成功登陆了。
头部.载荷.签名
JWT示例:
jwt的头部承载两部分信息:
- 声明类型,这里是jwt
- 声明加密的算法,一般直接使用 HMAC SHA256
完整的头部就像下面这样的JSON:
{
'typ': 'JWT',
'alg': 'HS256'
}
而后将头部进行base64编码, 构成了第一部分。
BASE64后的结果:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
载荷就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,这些有效信息包含:
标准中注册的声明 (建议但不强制使用) :
- iss: jwt签发者
- sub: jwt所面向的用户
- aud: 接收jwt的一方
- exp: jwt的过时时间,这个过时时间必需要大于签发时间
- nbf: 定义在什么时间以前,该jwt都是不可用的.
- iat: jwt的签发时间
- jti: jwt的惟一身份标识,主要用来做为一次性token,从而回避重放攻击。
其它声明 :好比,用户的相关信息或其余业务须要的必要信息
定义一个payload:
{
"user_name": "John Doe",
"user_id": 10}
BASE64后的结果:
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9注意:payload部分不能存放敏感信息,由于base64是能够解码的。
JWT的第三部分是一个签证(签名)信息,即对前两部分签名后获得的一个字符串。
签名:使用密钥(SECRECT_KEY )对数据进行加密,获得了一个值(签名)。
签名的做用:防止数据篡改,客户端传给服务器的jwt若是被修改过,服务器验签(校验)会不经过。
// javascript // header和payload部分用.链接起来 var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload); // 使用指定的算法签名 var signature = HMACSHA256(encodedString, 'secret'); // 签名结果: TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ