From 8e1f2b72b4935ddaac20700b07bcdc70ac8ee455 Mon Sep 17 00:00:00 2001 From: asahi Date: Mon, 24 Nov 2025 16:42:09 +0800 Subject: [PATCH] =?UTF-8?q?doc:=20=E9=98=85=E8=AF=BBjwt=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jwt/jwt.md | 182 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 158 insertions(+), 24 deletions(-) diff --git a/jwt/jwt.md b/jwt/jwt.md index 7316953..1acb2df 100644 --- a/jwt/jwt.md +++ b/jwt/jwt.md @@ -1,25 +1,159 @@ +- [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 -* ## jwt简介 - > jwt是一个开源标准。jwt定义了一个紧凑且自包含的方式安全的在多方之间通过json字符串传递信息。由于传递的信息会被签名,故而信息是可验证和信任的。 - jwt只能对payload中的信息进行验证,并不会对信息进行加密。故而jwt中不应该包含敏感信息。jwt只是对header和payload的信息进行签名,保证该信息的来源方式可信的。 -* ## jwt用途 - * jwt通常用来进行认证操作 - * jwt还可以用作信息交换,由于传递的信息会被签名,故而通过jwt来传输信息是安全的 -* ## jwt结构 - * ### Header - * 对于header部分的信息,会进行base64url编码 - * ### Payload - * 对于payload部分的数据,也会进行base64url形式的编码 - * - * ### Signature - * 通常,在header中记录了加密算法,对base64url编码后的header和payload用指定算法和服务端私钥技能型签名后,会生成签名部分 - * 将签名部分和header、payload通过.分隔并且连接,然后就可以生成jwt -* ## jwt认证流程 - * 首先,客户端第一次向服务端发送登录请求,服务端根据客户端发送的用户名、密码等登录信息在数据库中查找信息并验证,如果登录成功,会在服务端生成一个jwt - * 服务端会将生成的jwt返回给客户端,jwt中可以记录一些不敏感信息 - * 而后每次客户端向服务端发送请求时,都会携带jwt,服务端在接收到jwt后会对jwt中的信息进行验证 -* ## jwt相对于session存储用户信息的优势 - * jwt的数据存储在客户端中,故而其并不会像session一样占用服务端内存,能够有效减轻服务端的内存压力 - * 将一些非敏感信息存储在jwt中,可以避免服务端频繁的在数据库中查询信息 - * jwt是以json格式存储信息的,故而jwt可以跨语言 - * jwt可以解决跨域问题,不像cookie只能在同一父域名的不同子域名下共享 \ No newline at end of file +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 Exchange:JWT能够安全的在各方传递信息。由于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 +``` + +在http header中发送jwt时,必须避免jwt大小过大。部分server不接受超过8KB的headers。如果需要在jwt中集成较多信息,需要使用替代方案,例如`Auth0 Fine-Grained Authorization`。 + +下图展示了JWT获取和通过JWT访问API、资源的流程 + +How does a JSON Web Token work + +1. 应用或client会向authorization server请求授权 +2. 当授权被授予后,authorization server将会向应用返回access token +3. 应用将会使用token去访问受保护资源 + +需要注意,在使用signed tokens时,token中的所有内容都会暴露给用户和其他方,即使他们无法修改这些信息。即不应该在token中包含机密信息。 + +## JWT的validation和verification +jwt的validation和verification针对的是JWT的不同方面: +- validation:jwt的格式是否正确 +- verification:确保jwt真实且未修改 + +### Validation +JWT validation会检查jwt的结构、格式、内容: +- 结构:确保jwt是被`.`符号分隔的三个部分(header, payload, signature) +- format:校验每个部分都是使用Base64URL进行编码的的,并且payload包含预期的claims +- content:校验payload中的claims是否正确,例如过期时间(exp)、issued_at(iat)、not before(nbf)等,确保token没有过期,并且没有在生效前使用 + +### Verification +verification保证的是jwt的真实性和完整性 +- Signature Verification:其为验证的主要环节,会通过jwt的header和payload部分来校验jwt的signature部分。该部分会通过header中指定的算法(例如RSA/ECDSA/HMAC)来完成。如果签名不符合预期,token可能被修改或来源非可信源。 +- Issuer Verification:校验`iss` claim指定的内容是否和预期相符 +- Audience Check:确保`aud` claim和预期相符 + +