JWT 结构与声明
了解标头、载荷和签名。
JWT 结构与声明 是 CoddyKit 上的免费 C# Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 4 节课。
什么是 JWT
JSON Web 令牌(JWT)是一种紧凑且适合 URL 的令牌格式,用于在双方之间安全传输声明。在 ASP.NET Core 中,它是对无状态 API 进行身份验证的最常用方式。
JWT 只是一个由三个采用 Base64Url 编码的部分组成的字符串,各部分以点号连接:header.payload.signature。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0Iiwicm9sZSI6ImFkbWluIn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c标头
标头描述令牌的签名方式。它是一个小型 JSON 对象,经过 Base64Url 编码后成为第一段。
alg表示签名算法(例如 HS256、RS256),而typ几乎总是JWT。
{
"alg": "HS256",
"typ": "JWT"
}载荷
载荷包含声明——关于用户的陈述以及令牌的元数据。它是第二段。
重要提示:载荷只是经过编码,并未加密。任何人都可以解码它,因此绝不要在此处放入机密信息。
{
"sub": "1234",
"name": "Alice",
"role": "admin",
"exp": 1735689600
}签名
签名用于保证令牌未遭篡改。服务器会根据已编码的标头、已编码的载荷和一个密钥计算签名。
如果有人更改了载荷中的任何一个字符,签名就不再匹配,验证也会失败。
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secretKey
)注册声明
JWT 规范(RFC 7519)对一些声明名称进行了标准化。这些名称使用三个字母组成的简短键:
iss- 颁发者sub- 主题(用户 ID)aud- 受众exp- 过期时间(Unix 秒数)nbf- 生效时间不得早于此时间iat- 签发时间
{
"iss": "https://api.myapp.com",
"aud": "myapp-clients",
"sub": "42",
"exp": 1735689600,
"iat": 1735686000
}自定义声明
除了已注册的声明集合之外,您还可以添加应用程序所需的任意自定义声明,例如角色、权限、租户 ID、email 等。
请保持载荷较小:每个声明都会随每个请求传输。
{
"sub": "42",
"email": "alice@myapp.com",
"role": "admin",
"tenant_id": "acme",
"permissions": ["orders:read", "orders:write"]
}ASP.NET Core 中的声明
在 .NET 中,声明由 System.Security.Claims.Claim 类型表示。每个声明都是一个类型 / 值对。
验证 JWT 时,ASP.NET Core 会将载荷中的每个条目转换为用户 ClaimsPrincipal 上的一个 Claim。
var claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, "42"),
new Claim(ClaimTypes.Name, "Alice"),
new Claim(ClaimTypes.Role, "admin"),
new Claim("tenant_id", "acme")
};ClaimsPrincipal 和 ClaimsIdentity
经过身份验证的用户由 ClaimsPrincipal 表示,它封装了一个或多个 ClaimsIdentity 对象,而每个对象都包含一组声明。
在控制器中,您可以通过 User 访问它。
// Inside a controller action
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
bool isAdmin = User.IsInRole("admin");
string? tenant = User.FindFirst("tenant_id")?.Value;声明类型映射
默认情况下,JWT 处理程序会将较短的 JWT 键映射为较长的 URI 风格声明类型(例如,sub 会变为 ClaimTypes.NameIdentifier)。
若要保留原始的短名称,请在应用启动时禁用入站映射。
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
// Now User.FindFirst("sub") returns the raw 'sub' claim为什么不直接使用会话 Cookie
JWT 是自包含的:服务器只需使用签名密钥即可验证 JWT,无需查询数据库或使用服务器端会话存储。
因此,JWT 非常适合横向扩展的 API 和微服务,因为任意节点都可以验证同一个令牌。
// Client sends the token on every request:
// Authorization: Bearer eyJhbGciOiJIUzI1Ni...权衡:撤销
由于 JWT 是自包含的,并且在过期前始终受到信任,因此您无法轻易在其 exp 时间之前撤销它。
常见的缓解措施是让访问令牌的有效期较短,并将其与刷新令牌配合使用(本课程稍后会介绍)。
// Short-lived access token
exp = iat + 15 * 60; // 15 minutes快速检查
测试您对 JWT 结构的理解。
回顾
您已经学习了 JWT 的构成,以及声明在 ASP.NET Core 中的工作方式:
- JWT 由
header.payload.signature组成,每部分都经过 Base64Url 编码。 - 载荷包含已注册和自定义声明,这些声明经过编码但未加密。
- 签名使用密钥或密钥对来保证完整性。
- .NET 会将声明转换为
ClaimsPrincipal,您可以通过User读取它。
接下来,您将配置 ASP.NET Core 来验证这些令牌。
常见问题解答
「JWT 结构与声明」课时是免费的吗?
是的 — 「JWT 结构与声明」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 4 节课。
「JWT 结构与声明」这节课中我会学到什么?
了解标头、载荷和签名。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 C# Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「JWT 结构与声明」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 C# Academy 课中编写并运行代码吗?
能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- JWT 结构与声明
- 配置 JWT Bearer 身份验证
- 签发令牌
- 刷新令牌与过期