JSON Web Token(JWT)是一个开放式标准(RFC 7519),它定义了一种紧凑(Compact)且自包含(Self-contained)的方式,用于在各方之间以JSON对象安全传输信息。 这些信息能够经过数字签名进行验证和信任。 可使用秘密(使用HMAC算法)或使用RSA的公钥/私钥对对JWT进行签名。html
虽然JWT能够加密以提供各方之间的保密性,但咱们将重点关注已签名的令牌。 签名的令牌能够验证其中包含的索赔的完整性,而加密令牌隐藏来自其余方的索赔。 当令牌使用公钥/私钥对进行签名时,签名还证实只有持有私钥的方是签名方。算法
咱们来进一步解释一些概念:数据库
在紧凑的形式中,JWT包含三个由点(.)分隔的部分,它们分别是:跨域
JWT结构一般以下所示:安全
xxxxx.yyyyy.zzzzz
下面咱们分别来介绍这三个部分:服务器
Header一般由两部分组成:令牌的类型,即JWT。和经常使用的散列算法,如HMAC SHA256或RSA。
例如:cookie
{ "alg": "HS256", "typ": "JWT" }
Header部分的JSON被Base64Url编码,造成JWT的第一部分。session
这里放声明内容,能够说就是存放沟通信息的地方,在定义上有3种声明(Claims):less
Registered claims(注册声明):
这些是一组预先定义的声明,它们不是强制性的,但推荐使用,以提供一组有用的,可互操做的声明。 其中一些是:iss
(发行者),exp
(到期时间),sub
(主题),aud
(受众)等。#Registered Claim Names#ide
Private claims(私有声明):
这些是为了赞成使用它们可是既没有登记,也没有公开声明的各方之间共享信息,而建立的定制声明。
Playload示例以下:
{ "sub": "1234567890", "name": "John Doe", "admin": true }
Playload部分的JSON被Base64Url编码,造成JWT的第二部分。
请注意,对于已签名的令牌,此信息尽管受到篡改保护,但任何人均可以阅读。 除非加密,不然不要将秘密信息放在JWT的有效内容或标题元素中。这也是不少文章争论jwt安全性缘由,不要用 JWT 取代 Server-side 的 Session状态机制。详情请阅读这篇文章:Stop Using Jwt For Sessions.
第三部分signature用来验证发送请求者身份,由前两部分加密造成。
要建立签名部分,您必须采用编码标头,编码有效载荷,秘钥,标头中指定的算法并签名。
例如,若是你想使用HMAC SHA256算法,签名将按照如下方式建立:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
JWT输出的是三个由点分隔的Base64-URL字符串,能够在HTML和HTTP环境中轻松传递,而与基于XML的标准(如SAML)相比,它更加紧凑。
如下JWT示例,它具备先前的标头和有效负载编码,而且使用秘钥进行签名。
咱们可使用jwt.io调试器来解码,验证和生成JWT:
在身份验证中,当用户使用他们的凭证成功登陆时,JSON Web Token将被返回而且必须保存在本地(一般在本地存储中,但也可使用Cookie),而不是在传统方法中建立会话 服务器并返回一个cookie。
关于存储令牌(Token)的方式,必须考虑安全因素。
参考: #Where to Store Tokens#
不管什么时候用户想要访问受保护的路由或资源,用户代理都应使用承载方案发送JWT,一般在请求头中的Authorization
字段,使用Bearer
schema:
Authorization: Bearer <token>
这是一种无状态身份验证机制,由于用户状态永远不会保存在服务器内存中。 服务器受保护的路由将在受权头中检查有效的JWT,若是存在,则容许用户访问受保护的资源。 因为JWT是独立的,全部必要的信息都在那里,减小了屡次查询数据库的需求。
这使得咱们能够彻底依赖无状态的数据API,甚至向下游服务提出请求。 不管哪些域正在为API提供服务并不重要,所以不会出现跨域资源共享(CORS)的问题,由于它不使用Cookie。
请注意,使用已签名的令牌,令牌中包含的全部信息都会暴露给用户或其余方,即便他们没法更改它。 在JWT中,不该该在Playload里面加入任何敏感的数据,好比像密码这样的内容。若是将用户的密码放在了JWT中,那么怀有恶意的第三方经过Base64解码就能很快地知道你的密码了。
Base64编码方式是可逆的,也就是透过编码后发放的Token内容是能够被解析的。通常而言,咱们都不建议在有效载荷内放敏感讯息,好比使用者的密码。
JWT其中的一个组成内容为Signature,能够防止经过Base64可逆方法回推有效载荷内容并将其修改。由于Signature是经由Header跟Payload一块儿Base64组成的。
是的,Cookie丢失,就表示身份就能够被伪造。故官方建议的使用方式是存放在LocalStorage中,并放在请求头中发送。
JWT Token一般长度不会过小,特别是Stateless JWT Token,把全部的数据都编在Token里,很快的就会超过Cookie的大小(4K)或者是URL长度限制。
exp
时效不要设定太长。Only Http
预防XSS攻击。jti
(JWT ID),exp
(有效时间) Claim。[1] Stop using JWT for sessions:
http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/
[3] Use JWT The Right Way!:
https://stormpath.com/blog/jwt-the-right-way
[2] JSON Web Token 维基百科:
https://en.wikipedia.org/wiki/JSON_Web_Token