什么是JWT
JSON Web令牌(JWT)是一个开放标准,它定义了一种紧凑且自包含的方式,用于在各方之间安全地将信息作为JSON对象传输。由于此信息是经过数字签名的,因此可以进行验证和信任。可以使用密钥(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥配对对JWT进行签名。
尽管可以对JWT进行加密以提供双方之间的保密性,但我们将重点关注已签名的令牌。签名的令牌可以验证其中包含的声明的完整性,而加密的令牌则对第三方隐藏这些声明。当使用公钥/私钥对对令牌进行签名时,签名还可以证明只有持有私钥的一方才是对其进行签名的一方。
什么时候使用JWT
-
授权:这是使用JWT的最常见方案。一旦用户登录,每个后续请求将包括JWT,从而允许用户访问该令牌允许的路由,服务和资源。单点登录是当今广泛使用JWT的一项功能,因为它的开销很小并且可以在不同的域中轻松使用。
-
信息交换:JSON Web令牌是在各方之间安全地传输信息的好方法。因为可以对JWT进行签名(例如,使用公钥/私钥对),所以您可以确保发件人是他们所说的人。此外,由于签名是使用
header
和payload
计算的,因此您还可以验证内容是否遭到篡改。
JWT的结构
JSON Web令牌以紧凑的形式由三部分组成,这些部分由点(.
)分隔,分别是:
- 标头
- 有效载荷
- 签名
因此,JWT通常如下所示。
xxxxx.yyyyy.zzzzz
让我们分解不同的部分。
标头
标头通常由两部分组成:令牌的类型(即JWT
)和所使用的签名算法,例如HMAC SHA256
或RSA
。
例如:
{
"alg": "HS256",
"typ": "JWT"
}
然后,此JSON被Base64Url
编码,形成JWT的第一部分。
有效载荷
令牌的第二部分是有效负载payload
,这部分里包含声明。声明是有关实体(通常是用户信息)和其他数据的声明。声明有以下三种类型:registered
, public
, private
。
- registered:这些是一组非强制性的但建议使用的预定义的声明。其中一些是: iss(发出者), exp(到期时间), sub(subject), aud(audience)等。
请注意,声明名称仅是三个字符,因为JWT是紧凑的。
-
public:使用JWT的人员可以随意定义这些声明。但为避免冲突,它们应该在IANA JSON Web Token Registry 已被定义,或将其定义为不会冲突的名称URI。
-
private:这些是自定义声明,被用来在同意使用它们的各方之间分享信息,同时即非public又非registered。
有效负载示例可能是:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
然后,对payload进行Base64Url
编码,以形成JWT的第二部分。
请注意,对于已签名的令牌,此信息尽管可以防止篡改,但任何人都可以读取。除非将其加密,否则请勿将机密信息放入JWT的有效负载或标头中。
签名
要创建签名部分,您必须获取编码的标头(header),编码的有效载荷(payload),密钥(serect),标头中指定的算法,并对其进行签名。
例如,如果要使用HMAC SHA256
算法,则将通过以下方式创建签名:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
签名用于验证消息在此过程中没有被篡改过,并且对于使用私钥进行签名的令牌,它还可以验证JWT的发件人是谁。
放在一起
输出是三个由.
分隔的Base64-URL字符串,可以在HTML和HTTP环境中轻松传递这些字符串,与基于XML的标准(例如SAML)相比,它更紧凑。
下图显示了一个JWT,它已对先前的标头和有效负载进行了编码,并用一个秘密进行了签名。
JWT如何工作
在身份验证中,当用户成功登录时,将返回JSON Web令牌。由于令牌是凭据,因此必须格外小心以防止安全问题。通常,令牌的保留时间不应超过要求的时间。
由于缺乏安全性,您不应该将敏感的session数据存储在浏览器中。
每当用户想要访问受保护的路由或资源时,User agent 需要发送JWT令牌,通常在Authorization
头部使用Bearer
语法 。标头的内容应如下所示:
Authorization: Bearer <token>
在特定情况下,这可以是无状态授权机制。服务器的受保护路由将在Authorization标头中检查有效的JWT,如果存在,则将允许用户访问受保护的资源。如果JWT包含必要的数据,则可以减少查询数据库中某些操作的需求。
如果令牌是在Authorization
标头中发送的,则跨域资源共享(CORS)不会成为问题,因为它不使用cookie。
下图显示了如何获取JWT并将其用于访问API或资源:
- 应用程序或客户端向服务器请求授权。
- 授予授权后,授权服务器会将访问令牌返回给应用程序。
- 该应用程序使用访问令牌来访问受保护的资源(例如API)。
请注意,使用签名的令牌,令牌中包含的所有信息都将向用户或第三方公开,即使他们无法修改它。这意味着您不应将机密信息放入令牌中。
JWT的好处
与Simple Web Tokens (SWT)
and Security Assertion Markup Language Tokens (SAML)
相比:
- 尺寸: 更小,更紧凑
- 安全: JWT和SAML令牌可以使用X.509证书形式的公用/专用密钥对进行签名, 而且对JSON签名比XML更简单
- 简单:JSON直接映射对象,比XML断言更简单
- 用法:用法更简单,在多平台(如移动端)使用JWT更方便