JSON Web Token(JWT)是一种开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,可以安全地将信息以JSON对象的形式传递给双方。这个信息可以被验证和新人,因为它是数字签名的。JWT可以使用一个密钥(使用HMAC算法)或使用RSA的公钥/私钥来签名。
虽然JWT可以加密,也可以在各方之间提供加密,但我们将重点关注已签署的令牌。签名的令牌可以验证其中包含的声明的完整性,而加密的令牌可以隐藏来自其他地方的声明。当使用公钥/私钥对 签署令牌时,签名也证明只有持有私钥的一方是签名方。
让我们进一步解释一些概念。
Compact(紧凑):由于它们的大小比较小,JWT可以通过URL、POST参数或HTTP报头发送。此外,较小的尺寸意味着传输速度很快。
自包含:有效载荷包含用户所需的所有信息,避免多次查询数据库。
下面是一些JSON Web令牌有用的场景:
身份验证:这是使用JWT最常见的场景。用户登录后,每个后续的请求将包括JWT,允许用户访问该令牌允许的路由、服务和资源。单点登录时目前广泛使用JWT的一个特性,因为它开销很小,并且能够很容易地跨不同的域使用。
信息交换:JSON Web令牌是在双方之间安全地传输信息的一种好方法。因为JWT可以是签名的--例如,使用公钥/私钥部分--你可以确定发送者是他们说得那些人。另外由于签名是使用header和有效载荷计算的,您可以验证内容没有被篡改。
在其紧凑的形式中,JSON Web令牌由点(.)分隔的三个部分组成:
Header
有效载荷(Payload)
签名(Signature)
因此,JWT通常看起来像下面这样。
xxxxx.yyyyy.zzzzz
让我们分解不同的部分。
Header通常由两部分组成:标记的类型-JWT,正在使用的散列算法,例如HMAC SHA256或RSA。
例如:
{ "alg": "HS256", "typ": "JWT" }
然后,这个JSON是由Base64Url编码的,以形成JWT的第一部分。
令牌的第二部分是负载,它包含声明。声明是关于实体(通常是用户)和其他元数据的声明。声明有三种类型:注册、公共和私有的。
注册声明:这是一组预定义的声明,这些声明不是强制的,而是推荐的,以提供一组有用的、可互操作的声明。其中一些是:iss(发行者),exp(过期时间), sub(主题),aud(受众)等。注意:,声明名称只有3个字符,因为JWT旨在紧凑。
公共声明:这些可以由使用JWT的人来定义。但是为了避免冲突,它们应该在IANA JSON Web Token中定义,或者被定义为包含一个抗冲突名称空间的URI。
私有声明:这些事用来在双方之间共享信息的自定义声明,他们同意使用这些嘻嘻你,并且没有注册或公开声明。
一个有效载荷可以是:
{ "sub": "1234567890", "name": "John Doe", "admin": true }
负载是由Base64Url编码的,以形成JSON Web令牌的第二部分。
请注意,对于已签名的令牌,此信息虽然不受篡改,单任何人都可读。不要在JWT的有效载荷或header中放入私密信息,除非它是加密的。
要创建签名部分,您必须使用编码的header、编码的有效负载、一个secret、在header中指定的算法,并签名。
例如,如果您想要使用HMAC SHA256算法,签名将以以下方式创建:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
签名用于验证消息在过程中没有被更改,并且,在用私钥签名的情况下,您还可以验证JWT的发送者是谁。
输出是三个Base64-URL字符串,这些字符串由可以在HTML和HTTP环境中轻松传输的点(.)分隔,而与像SAML这样的基xml的标准相比,它更紧凑。
下面显示了一个JWT,它有前面的header和有效载荷的编码,并且它附加了一个secret的签名。
如果你想要使用JWT并将这些概念付诸实践,您可以使用jwt.id Debugger解码、验证和生成JWT。
在身份验证中,当用户成功地使用他们的凭证登录时,将返回一个JSON Web令牌,并且必须在本地保存(通常在本地存储中,单也可以使用cookie),而不是在服务器上创建会话并返回cookie的传统方法。
有一些安全因素必须考虑到令牌存储方式。这些事在哪里存储标记的枚举 Where to Store Tokens。
当用户想要访问受保护的路由或资源时,用户代理应该发送JWT,通常在授权Header中使用承载模式。标题的内容应该如下所示:
Authorization: Bearer <token>
这是一个无状态的身份验证机制,因为用户状态永远不会保存在服务器内存中。服务器的受保护路由将在授权header中检查有效的JWT,如果它存在,用户将被允许访问受保护的资源。由于JWT是自包含的,所有所有必要的信息都在那里,从而减少了多次查询数据库的需求。
这允许您完全依赖无状态的数据api,甚至可以向下游服务器发出请求。哪个域为您的api服务并不重要,所以跨源资源共享(CORS)不会成为一个问题,因为它不使用cookie。
下图显示了这个过程:
请注意,在带有签名的标记的情况下,令牌中包含的所有信息都将暴露给用户或其他参与方,即使他们无法更改它。这意味着不应该再令牌中放机密信息。
让我们讨论一下JSON Web令牌(JWT)与简单的Web令牌(SWT)和安全标记语言令牌(SAML)的好处。
由于JSON比XML更少,当它被编码时,它的大小也更小,使用JWT比SAML更紧凑。这使得JWT可以在HTML和HTTP环境中被传递。
安全方面,SWT只能通过使用HMAC算法的共享密钥来对称的签名。但是,JWT和SAML令牌可以使用一个公共/私有密钥对,以X.509证书的形式签名。与简单的签名JSON相比,在不引入晦涩的安全漏洞的情况下使用XML数字签名来签署XML是非常困难的。
JSON解析器在大多数编程语言中都很常见,因为它们直接映射到对象。相反,XML没有自然的文档到对象的映射。这使得使用JWT比SAML断言更容易。
关于使用,JWT在互联网规模使用。这块显示了在多个平台上的JSON Web标记的客户端处理的易用性,尤其是移动端。
编码JWT和编码SAML的长度的比较。
如果你想阅读更多关于JSON Web令牌的内容,甚至开始使用它们在自己的应用程序中执行身份验证,请浏览Auth0的JSON Web Token 登录页面