目录
- 1. What is JSON Web Token?( jwt 是啥玩意?)
- 2. When should you use JSON Web Tokens?(什么时候使用 jwt?)
- 3. What is the JSON Web Token structure? ( jwt 结构什么样子?)
- 4. How do JSON Web Tokens work?(jwt 如何工作的?)
- 5. Difference Between Validating and Verifying a JWT(JWT 验证与校验的区别)
- 6. Difference Between Decoding and Encoding a JWT(JWT 编码与解码的区别)
- 说明
在我们研究 jwt 之前,可以稍微想了解一下 token
(令牌) 和 signature
(签名)
1. What is JSON Web Token?( jwt 是啥玩意?)
原文: JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA. |
JSON Web Token(JWT)是一种开放标准(RFC 7519),它定义了一种简洁且自包含的方式,用于在各方之间以 JSON 对象的形式安全传输信息。这些信息之所以可验证且可信,是因为它经过了数字签名。JWT 可通过密钥进行签名(使用 HMAC 算法),也可通过 RSA 或 ECDSA 算法(非对称加密算法)使用公钥 / 私钥对进行签名。
原文:Although JWTs can be encrypted to also provide secrecy between parties, we will focus on signed tokens. Signed tokens can verify the integrity of the claims contained within it, while encrypted tokens hide those claims from other parties. When tokens are signed using public/private key pairs, the signature also certifies that only the party holding the private key is the one that signed it. |
虽然 JWTs 可以通过加密来在各方之间提供保密性,但我们将重点关注签名令牌。签名令牌能够验证其中包含的声明的完整性,而加密令牌则对其他方隐藏这些声明。当令牌使用公钥 / 私钥对进行签名时,签名还能证明只有持有私钥的一方才是签名的主体。
2. When should you use JSON Web Tokens?(什么时候使用 jwt?)
使用 jwt 的几个场景:
原文: Authorization: This is the most common scenario for using JWT. Once the user is logged in, each subsequent request will include the JWT, allowing the user to access routes, services, and resources that are permitted with that token.Single Sign On is a feature that widely uses JWT nowadays because of its small overhead and its ability to be easily used across different domains. |
Authorization(授权)
:这是使用 JWT 最常见的场景。一旦用户登录,每个后续请求都会包含 JWT,使用户能够访问该令牌所允许的路由、服务和资源。单点登录是如今广泛使用 JWT 的一项功能,因为它开销小,且能够轻松跨不同域使用。
原文: Information Exchange: JSON Web Tokens are a good way of securely transmitting information between parties. Because JWTs can be signed—for example, using public/private key pairs—you can be sure the senders are who they say they are. Additionally, as the signature is calculated using the header and the payload, you can also verify that the content hasn't been tampered with. |
信息交换
:JSON Web Tokens(JWT)是在各方之间安全传输信息的一种很好的方式。由于 JWT 可进行签名 —— 例如,使用公钥 / 私钥对 —— 你可以确保发送者的身份与他们声称的一致。此外,由于签名是通过头部和载荷计算得出的,你还能验证内容未被篡改。
3. What is the JSON Web Token structure? ( jwt 结构什么样子?)
使用紧凑格式,JSON Web 令牌由三部分组成,各部分由点(.)分隔,它们分别是:
- Header
- Payload
- Signature
一个 JWT 通常如下:
xxxxx.yyyyy.zzzzz
3.1 Header(头部)
Header 通常由两部分组成:一是令牌的类型(即 JWT),二是所使用的签名算法,例如 HMAC SHA256 或 RSA。
For example(例子):
{
"alg": "HS256",
"typ": "JWT"
}
这个 JSON 经过 Base64Url
编码,形成 JWT 的第一部分。
3.2 Payload(载荷)
原文:The second part of the token is the payload, which contains the claims. Claims are statements about an entity (typically, the user) and additional data. There are three types of claims: registered, public, and private claims. |
令牌的第二部分是载荷,其中包含声明。声明是关于实体(通常为用户)的陈述以及附加数据。声明分为三类:注册声明、公共声明和私有声明。
- Registered claims(注册声明):
原文:These are a set of predefined claims which are not mandatory but recommended, to provide a set of useful, interoperable claims. Some of them are: iss (issuer), exp (expiration time), sub (subject), aud (audience), and others. Notice that the claim names are only three characters long, as JWT is meant to be compact. |
需要注意的是,声明名称仅为三个字符,因为 JWT 的设计初衷是保持紧凑性。
下面是一些常见的注册声明:
iss(issuer)
:JWT 签发方。iat(issued at time)
:JWT 签发时间。sub(subject)
:JWT 主题。aud(audience)
:JWT 接收方。exp(expiration time)
:JWT 的过期时间。nbf(not before time
):JWT 生效时间,早于该定义的时间的 JWT 不能被接受处理。jti(JWT ID)
:JWT 唯一标识。
这些官方的注册声明,都是三个字母。
- Public claims(公共声明):
原文:These can be defined at will by those using JWTs. But to avoid collisions, they should be defined in the IANA JSON Web Token Registry or be defined as a URI that contains a collision-resistant namespace. |
使用 JWT 的用户可自行定义这类声明。但为避免冲突,它们应在 IANA JWT 注册表中进行定义,或定义为包含防冲突命名空间的 URI。
- Private claims(私有声明):
原文:These are the custom claims created to share information between parties that agree on using them and are neither registered or public claims. |
这类声明是为在同意使用它们的各方之间共享信息而创建的自定义声明,既不属于注册声明,也不属于公共声明。
一个Payload
(载荷)示例如下:
{
"sub": "1234567890", // 官方的 注册声明
"exp": 15323232, // 官方的 注册声明
"iat": 1516239022, // 官方的 注册声明
"name": "John Doe", // 自定义的声明
"admin": true
}
然后,载荷经过 Base64Url 编码,形成 JSON Web 令牌的第二部分。
原文: Do note that for signed tokens, this information, though protected against tampering, is readable by anyone. Do not put secret information in the payload or header elements of a JWT unless it is encrypted. |
请注意,对于签名令牌,尽管此类信息可防止篡改,但任何人都能读取。请勿在 JWT 的载荷或头部元素中放入机密信息,除非经过加密。
3.3 Signature(签名)
原文: To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that. |
要创建签名部分,你需要获取编码后的Header、编码后的payload、一个密钥、Header中指定的算法,并对其进行签名。
例如,如果你想使用 HMAC SHA256 算法,签名将通过以下方式创建:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
签名用于验证消息在传输过程中未被更改;而且,对于使用私钥签名的令牌,它还能验证 JWT 的发送者确实是其声称的身份。
3.4 Putting all together (综合起来)
原文: The output is three Base64-URL strings separated by dots that can be easily passed in HTML and HTTP environments, while being more compact when compared to XML-based standards such as SAML. |
其输出是三个用点分隔的 Base64-URL 编码字符串,这些字符串可轻松在 HTML 和 HTTP 环境中传输,且与基于 XML 的标准(如 SAML)相比更为简洁。
以下示例展示了一个 JWT,它包含已编码的上述头部和载荷,并用密钥进行了签名。
如果你想尝试使用 JWT 并将这些概念付诸实践,可以使用 jwt.io(这是一个jwt的调试工具) 调试器来解码、验证和生成 JWT。
4. How do JSON Web Tokens work?(jwt 如何工作的?)
原文: In authentication, when the user successfully logs in using their credentials, a JSON Web Token will be returned. Since tokens are credentials, great care must be taken to prevent security issues. In general, you should not keep tokens longer than required. You also should not store sensitive session data in browser storage due to lack of security. |
此外,由于安全性不足,不应将敏感的会话数据存储在浏览器存储中。
无论何时,用户想要访问受保护的路由或资源,用户代理应发送 JWT,通常是在 Authorization 头部中使用 Bearer 模式。该头部的内容如下所示:
Authorization: Bearer <token>
原文:This can be, in certain cases, a stateless authorization mechanism. The server's protected routes will check for a valid JWT in the Authorization header, and if it's present, the user will be allowed to access protected resources. If the JWT contains the necessary data, the need to query the database for certain operations may be reduced, though this may not always be the case. Note that if you send JWT tokens through HTTP headers, you should try to prevent them from getting too big. Some servers don't accept more than 8 KB in headers. If you are trying to embed too much information in a JWT token, like by including all the user's permissions, you may need an alternative solution, like Auth0 Fine-Grained Authorization. If the token is sent in the Authorization header, Cross-Origin Resource Sharing (CORS) won't be an issue as it doesn't use cookies. |
在某些情况下,这是一种无状态的授权机制。服务器的受保护路由会检查 Authorization 头部中是否存在有效的 JWT,若存在,用户将被允许访问受保护资源。如果 JWT 中包含必要的数据,某些操作对数据库的查询需求可能会减少,不过情况并非总是如此。
请注意,若通过 HTTP 头部发送 JWT 令牌,应尽量防止其过大。有些服务器不接受头部大小超过 8 KB 的请求。如果试图在 JWT 令牌中嵌入过多信息(例如包含用户的所有权限),可能需要采用替代方案,比如 Auth0 细粒度授权。
如果令牌通过 Authorization 头部发送,跨域资源共享(CORS)不会成为问题,因为这种方式不使用 Cookie。
下图展示了 JWT 的获取方式以及如何使用它访问 API 或资源:
原文: 1. The application or client requests authorization to the authorization server. This is performed through one of the different authorization flows. For example, a typical OpenID Connect compliant web application will go through the /oauth/authorize endpoint using the authorization code flow. 2. When the authorization is granted, the authorization server returns an access token to the application. 3. The application uses the access token to access a protected resource (like an API). |
上图三个箭头的含义:
- 应用程序或客户端向授权服务器请求授权。这一过程通过多种不同的授权流程之一来完成。例如,一个典型的符合OpenID Connect标准的Web应用会通过 /oauth/authorize 端点,采用授权码流程进行操作。(笔记:我们大部分时候就是通过 用户名、密码登录方式)
- 当授权被批准后,授权服务器会向应用返回一个访问权限的token(令牌)。
- 应用程序使用该访问令牌访问受保护资源(例如API)。
原文:Do note that with signed tokens, all the information contained within the token is exposed to users or other parties, even though they are unable to change it. This means you should not put secret information within the token |
5. Difference Between Validating and Verifying a JWT(JWT 验证与校验的区别)
原文:JSON Web Token (JWT) validation and verification are crucial for security, but they address slightly different aspects of JWT security: validation ensures the token is well-formed and contains enforceable claims; verification ensures the token is genuine and unmodified. |
JSON Web Token(JWT)的验证(validation)和校验(verification)对安全性至关重要,但它们针对 JWT 安全的不同层面:验证确保令牌格式正确且包含可执行的声明(生成阶段);校验确保令牌真实且未被篡改(校验阶段)。
下面详细探讨验证与校验的区别:
JWT 验证通常指检查 JWT 的结构、格式和内容:
原文: Structure: Ensuring the token has the standard three parts (header, payload, signature) separated by dots. Format: Verifying that each part is correctly encoded (Base64URL) and that the payload contains expected claims. Content: Checking if the claims within the payload are correct, such as expiration time (exp), issued at (iat), not before (nbf), among others, to ensure the token isn't expired, isn't used before its time, etc. |
- 结构:确保令牌包含标准的三部分(头部、载荷、签名),且各部分用点分隔。
- 格式:验证各部分是否经过正确的 Base64URL 编码,以及载荷中是否包含预期的声明。
- 内容:检查载荷中的声明是否有效,例如过期时间(exp)、签发时间(iat)、生效时间(nbf)等,确保令牌未过期、未提前使用等。
而 JWT 校验则涉及确认令牌的真实性和完整性:
原文:
|
签名校验:这是校验的核心环节,通过头部指定的算法(如 HMAC、RSA 或 ECDSA),使用密钥或公钥将 JWT 的签名部分与头部和载荷进行比对。如果签名与预期不符,说明令牌可能被篡改或来自非可信来源。
签发者校验:检查 iss 声明是否与预期的签发者一致。
受众校验:确保 aud 声明与预期的受众一致。(注:audience
就是 jwt的接受者 )
从实际应用来看:
原文:
| |
验证 JWT 是为了确保令牌符合预期标准、逻辑合理且包含正确的数据。
校验 JWT 是为了确保令牌未被恶意篡改且来自可信来源。
在许多系统中,这些步骤通常被合并为通俗意义上的 “JWT 校验”,涵盖验证和校验以实现全面的安全检查。尽管如此,二者的区别仍然存在。
6. Difference Between Decoding and Encoding a JWT(JWT 编码与解码的区别)
原文:
| |
JWT 编码的工作就是** 将头部和载荷转换为紧凑的、URL 安全格式 **。头部声明了签名算法和令牌类型,载荷包含主题、过期时间、签发时间等声明,二者都会先转换为 JSON 格式,再进行 Base64URL 编码。这些编码后的部分用点号连接,之后使用头部中指定的算法以及密钥或私钥生成签名。该签名也会经过 Base64URL 编码,最终形成适合传输或存储的 JWT 字符串。
原文:
| |
JWT 解码则是上述过程的逆操作,它将经过 Base64URL 编码的头部和载荷转换回 JSON 格式,因此任何人无需密钥即可读取这些部分。不过,在这一语境中,“解码” 通常还包含对令牌签名的验证。验证步骤包括使用相同的算法和密钥对解码后的头部和载荷重新签名,然后将新生成的签名与 JWT 中包含的签名进行比对。如果二者匹配,则可确认令牌的完整性和真实性,表明其自签发以来未被篡改过。
说明
- 文章大部分内容来源于 AUTH0 的 jwo.io.
- 大部分翻译为AI翻译。