JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于作为JSON对象在各方之间安全地传输信息。可以验证和信任此信息,因为它是数字签名的。JWTs可以使用密钥(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。
虽然JWTs也可以加密以在各方之间提供保密性,但我们将重点关注已签名的令牌。签名的令牌可以验证其中包含的声明的完整性,而加密的令牌则可以向其他方隐藏这些声明。当使用公钥/私钥对对令牌进行签名时,签名也能证明只有持有私钥的一方才是签名的一方。
下面是一些JSON Web令牌非常有用的场景:
在其紧凑的形式中,JSON Web令牌由点(.)分隔的三部分组成,分别是:
让我们把不同的部分分开:
Header
头通常由两部分组成:令牌的类型(JWT)和正在使用的签名算法(如HMAC SHA256或RSA)。
比如:
{
"alg": "HS256",
"typ": "JWT"
}
然后,对这个JSON进行Base64Url编码,以形成JWT的第一部分。
Payload
令牌的第二部分是有效负载,它包含声明。声明是关于实体(通常是用户)和其他数据的语句。声明有三种类型:注册声明、公开声明和私人声明。
注意,声明名称只有三个字符长,只是出于JWT的显得紧凑缘故。
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
然后对有效负载进行Base64Url编码,以形成JSON Web令牌的第二部分。
注意,对于已签名的令牌,此信息虽然受保护不受篡改,但任何人都可以读取。除非加密,否则不要将机密信息放入JWT的有效负载或头元素中。
例如,如果您想使用HMAC SHA256算法,签名将按照以下方式创建
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
签名用于验证消息在整个过程中没有被更改,并且,对于使用私钥签名的令牌,它还可以验证JWT的发送方就是它所说的发送方。
下面显示了一个JWT,包含了前面编码了的头部(header)、有效负载(payload),和一个用秘钥对前面两部份的签名:
如果您想使用JWT并将这些概念付诸实践,您可以使用 jwt.io Debugger解码、验证和生成JWTs。
在身份验证中,当用户使用其凭证成功登录时,将返回一个JSON Web令牌。由于令牌是凭证,因此必须非常小心地防止安全问题。一般来说,您不应该保留令牌超过要求的时间.
当用户希望访问受保护的路由或资源时,用户代理应该发送JWT,通常在Authorization授权头中使用 Bearer模式。标题的内容应该如下:
Authorization: Bearer
在某些情况下,这可以是一种无状态授权机制。服务器的受保护路由将在Authorization授权头中检查有效的JWT,如果它存在,用户将被允许访问受保护的资源。如果JWT包含必要的数据,就可以减少对数据库查询某些操作的需求,尽管情况并非总是如此。
如果令牌是在授权头中发送的,那么跨源资源共享(Cross-Origin Resource Sharing, CORS)就不是问题,因为它不使用cookie。
请注意,对于已签名的令牌,令牌中包含的所有信息都公开给用户或其他方,即使他们无法更改这些信息。这意味着您不应该将机密信息放在令牌中。
让我们讨论一下与简单Web令牌(SWT)和安全断言标记语言令牌(SAML)相比,JSON Web令牌(JWT)的好处。
由于JSON比XML更简洁,当它被编码时,它的大小也更小,这使得JWT比SAML更紧凑。这使得JWT成为在HTML和HTTP环境中传递消息的一个很好的选择。
在安全方面,SWT只能由使用HMAC算法的共享秘钥对称签名。但是,JWT和SAML令牌可以使用X.509证书形式的公钥/私钥对进行签名。与JSON签名的简单性相比,使用XML数字签名签名XML而不引入模糊的安全漏洞是非常困难的。
JSON解析器在大多数编程语言中都很常见,因为它们直接映射到对象。相反,XML没有一个自然的文档到对象的映射。这使得使用JWT比使用SAML断言更容易。
在使用方面,JWT被用于面向互联网。这突出了JSON Web令牌在多个平台(尤其是移动平台)上的客户端处理的易用性。
参考:https://jwt.io/introduction/