0Pricing
C# Academy · 课时

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 反馈 — 无需本地设置。

此课程中的所有课时

  1. JWT 结构与声明
  2. 配置 JWT Bearer 身份验证
  3. 签发令牌
  4. 刷新令牌与过期
← 返回 C# Academy