Files
rikako-note/jwt/jwt.md
2025-11-24 16:42:09 +08:00

160 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

- [JWT](#jwt)
- [JWT应用场景](#jwt应用场景)
- [JSON Web Token结构](#json-web-token结构)
- [Header](#header)
- [Payload](#payload)
- [registered claims](#registered-claims)
- [Public claims](#public-claims)
- [private claims](#private-claims)
- [Signature](#signature)
- [putting together](#putting-together)
- [JSON Web Tokens工作方式](#json-web-tokens工作方式)
- [JWT的validation和verification](#jwt的validation和verification)
- [Validation](#validation)
- [Verification](#verification)
# JWT
JSON Web Token是一个开源标准定义了一种`紧凑且自自包含`的方式用于在各方之间安全的传输信息这些信息以JSON对象的形式呈现。传输的信息是被数字签名的故而信息可以被验证并信任。
JWT可以通过密钥使用hmac算法或public/private key pair使用RSA/ECDSA算法来进行签名。
即使JWT可以通过加密在传递过程中提供安全性但是本文会集中在signed tokens
- `signed tokens` signed tokens可以验证token中包含声明的完整性
- `encrypted tokens` 加密则是将token中的claims内容向第三方隐藏
## JWT应用场景
如下是JWT的常用场景
- Authorization这是JWT的最通用场景。一旦用户登录后续的请求都会包含JWT允许用户访问该JWT被允许的路由、服务、资源。
- `单点登录`特性普遍使用JWT其带来开销较小并且能够轻松的跨domains使用
- Information ExchangeJWT能够安全的在各方传递信息。由于JWT可以被签名例如在使用public/private key时可以确保发送方身份的可靠性。
- 并且由于签名是通过header和payload进行计算的还可以用于验证token内容是否被修改
## JSON Web Token结构
JWT的结构较为紧凑由三个部分组成三个部分之间通过`.`进行分隔:
- Header
- Payload
- Sinature
因此JWT通常看起来如下
```
xxxxx.yyyyy.zzzzz
```
### Header
header通常由两部分组成
- token的类型JWT
- 使用的签名算法: HMAC/SHA256/RSA
示例如下所示:
```json
{
"alg": "HS256",
"typ": "JWT"
}
```
`对于JWT的第一部分而言json形式的内容会被以Base64Url的形式进行编码`
### Payload
token的第二部分是payload包含了token中的claims
- `claim`:即对某个实体及其附加数据的描述(实体通常是用户)
claims通常存在三种类型
- registered
- public
- private
#### registered claims
存在一系列预定义的claims并非强制但是推荐进行使用。
- `iss`: issuer签发者
- `exp`: expiration time过期时间
- `sub`subject主体例如用户唯一标识
- `aud`audience接收方/受众指JWT的目标接收方限制token的使用范围
#### Public claims
pubic claims可以被jwt的使用者任意定义。但是为了避免冲突public claims应该在`IANA JSON Web Token Registry`中被定义或在命名中包含namespace从而避免冲突。
#### private claims
private claims也可以被自由定义用于在各方之间共享信息。
private claims和public claims的区别如下
- private claims可以被任意定义只需要传递的双方协商一致即可
- public claims的命名需要遵守相应规范应在`IANA JSON Web Token Registry`中或以URI的形式定义
payload的示例如下所示
```json
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
```
作为JWT的第二部分上述内容也会通过Base64Url的形式进行编码。
### Signature
为了创建jwt的第三部分必须接收如下内容
- encoded header
- encoded payload
- secret
- header中指定的算法
可以根据上述内容生成签名。
例如,如果使用`HMAC SHA256`算法进行签名,签名应当以如下方式进行创建:
```
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
```
> HMACSHA256是一种基于hash的消息认证码算法需要提供secret和待散列的消息
signature会被用于验证token内容是否被修改并且在使用private key进行签名时可以验证jwt的签发方身份。
### putting together
最终的jwt会将上述三个部分通过`.`分隔符拼接在一起。
## JSON Web Tokens工作方式
在认证过程中当用户通过凭据成功登录后系统将会返回一个jwt。返回的token本身就是凭据需谨慎对待避免出现安全问题。
通常不应该在jwt中存储敏感的会话数据。
不论何时当用户想要访问受保护的route和resource时user agent都应该发送JWT。通常JWT被包含在`Authorization` header中并使用`Bearer` schema。header的内容如下所示
```
Authorization: Bearer <token>
```
在http header中发送jwt时必须避免jwt大小过大。部分server不接受超过8KB的headers。如果需要在jwt中集成较多信息需要使用替代方案例如`Auth0 Fine-Grained Authorization`
下图展示了JWT获取和通过JWT访问API、资源的流程
<img alt="How does a JSON Web Token work" loading="lazy" width="480" height="480" decoding="async" data-nimg="1" class="markdown-image_image__vmfuh" sizes="100vw" src="https://www.jwt.io//_next/image?url=https%3A%2F%2Fcdn.auth0.com%2Fwebsite%2Fjwt%2Fintroduction%2Fclient-credentials-grant.png&w=3840&q=75" style="color:transparent;width:100%;height:auto">
1. 应用或client会向authorization server请求授权
2. 当授权被授予后authorization server将会向应用返回access token
3. 应用将会使用token去访问受保护资源
需要注意在使用signed tokens时token中的所有内容都会暴露给用户和其他方即使他们无法修改这些信息。即不应该在token中包含机密信息。
## JWT的validation和verification
jwt的validation和verification针对的是JWT的不同方面
- validationjwt的格式是否正确
- verification确保jwt真实且未修改
### Validation
JWT validation会检查jwt的结构、格式、内容
- 结构确保jwt是被`.`符号分隔的三个部分header, payload, signature
- format校验每个部分都是使用Base64URL进行编码的的并且payload包含预期的claims
- content校验payload中的claims是否正确例如过期时间exp、issued_atiat、not beforenbf确保token没有过期并且没有在生效前使用
### Verification
verification保证的是jwt的真实性和完整性
- Signature Verification其为验证的主要环节会通过jwt的header和payload部分来校验jwt的signature部分。该部分会通过header中指定的算法例如RSA/ECDSA/HMAC来完成。如果签名不符合预期token可能被修改或来源非可信源。
- Issuer Verification校验`iss` claim指定的内容是否和预期相符
- Audience Check确保`aud` claim和预期相符