JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且独立的方法,用于在各方之间安全地将信息作为JSON对象传输。 由于此信息是经过数字签名的,因此可以被验证和信任。 可以使用密钥(使用HMAC算法)或使用RSA或ECDSA的公用/专用密钥对对JWT进行签名。
尽管可以对JWT进行加密以在各方之间提供保密性,但我们将重点关注已签名的令牌。 签名的令牌可以验证其中包含的声明的完整性,而加密的tokens则将这些声明隐藏在其他方的面前。 当使用公钥/私钥对对token进行签名时,签名还证明只有持有私钥的一方才是对其进行签名的一方。
有如下几个场景使用JWT是有帮助的:
JWT 以紧凑的形式由三部分组成,这些部分由点(.)分隔,分别是:
典型的JWT如:xxxxx.yyyyy.zzzzz
Header包含两部分, token类型,值为JWT,签名算法,如HMAC SHA256 或 RSA。例如:
{ "alg": "HS256", "typ": "JWT" }
Header JSON使用Base64Url 编码作为JWT的第一部分。
JWT第二部分是负载,其中包含claims。 claims是有关实体(通常是用户)和其他数据的声明。 共有三种类型的claims:注册,公有和私有声明。
Payload 结构如下:
{ "sub": "1234567890", "name": "John Doe", "admin": true }
payload 使用Base64Url 编码作为JWT的第二部分。请注意,对于已签名的Token,此信息尽管可以防止篡改,但任何人都可以读取。 除非将其加密,否则请勿将机密信息放入JWT的Payload 或Header元素中。
要创建签名部分,您必须获取编码的Header,编码的Payload 和一个密钥,使用Header中指定的算法对其进行签名。
例如使用 HMAC SHA256算法,signature 创建类似如下:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
该签名用于验证消息在此过程中是否未被更改,并且对于使用私钥进行签名的Token,它还可以验证JWT的发送者是他本人。
在身份验证中,当用户使用其凭据成功登录时,将返回JWT。 由于Token是凭据,因此必须格外小心以防止安全问题。 通常,Token的保留时间不应超过需要的时间。由于缺乏安全性,您也不应该将敏感的会话数据存储在浏览器中。
每当用户想要访问受保护的路径或资源时,用户代理通常应使用Bearer 模式在Header Authorization 中发送JWT。 header 的内容应如下所示:
Authorization: Bearer
在某些情况下,这可以是无状态授权机制。 服务器的受保护路径将在Authorization header中检查有效的JWT,如果存在,则将允许用户访问受保护的资源。 如果JWT包含必要的数据,则可以减少查询数据库中某些操作的需求。如果Token是在 Authorization Header中发送的,则可以支持跨域资源共享(CORS)。
下图显示了如何获取JWT并将其用于访问API或资源:
(1)应用程序或客户端向授权服务器请求授权。 这是通过一个简单的授权流程执行的。 例如,一个典型的符合OpenID Connect的Web应用程序将使用授权代码流程通过/oauth/authorize端点。
(2)授予认证后,授权服务器会将access token返回给应用程序。
(3)应用程序使用access token访问受保护资源。
请注意,使用签名的Token,Token中包含的所有信息都会暴露给用户或其他方,即使他们无法更改它。 所以不应将机密信息放入Token中。
由于JSON没有XML那么冗长,因此在编码时JSON的大小也较小,从而使JWT比Security Assertion Markup Language Tokens (SAML)更为紧凑。 这使得JWT是在HTML和HTTP环境中传递的不错的选择。
在安全方面,Simple Web Tokens (SWT)只能被对称签名通过使用HMAC算法由共享秘钥进行。 但是,JWT和SAML Token可以使用X.509证书形式的公私钥对进行签名。 与签名JSON的简单性相比,使用XML数字签名对XML进行签名而不引入模糊的安全漏洞是非常困难的。
JSON解析器在大多数编程语言中都很常见,因为它们直接映射到对象。 相反,XML没有自然的文档和对象映射。 与SAML相比,这使JWT更加容易使用。
关于用法,JWT是在Internet规模上使用的。 这强调了在多个平台(尤其是移动平台)上对JWT进行客户端处理的简便性。
(1)JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。
(2)JWT 不加密的情况下,不能将秘密数据写入 JWT。
(3)JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。
(4)JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。同时也不便于查询实时在线用户。
(5)JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。
(6)为了减少盗用,JWT 不应该使用 HTTP 协议明文传输,要使用 HTTPS 协议传输。
(7)客户端接收服务器返回的JWT,将其存储在Cookie或localStorage中。存储在Cookie中,就可以自动发送,但是不会跨域。为了支持跨域一般将它放入HTTP请求的Header Authorization字段中或者放置于POST请求的数据主体中。