OAuth 2.0 和 JWT 在 C# 中的简介
\n现代 Web 应用程序需要可靠的安全机制。两个关键协议——OAuth 2.0 和 JWT(JSON Web Token)——已成为实现授权和身份验证的事实标准。在本文中,我们将探讨如何在 C# (.NET) 生态系统中使用这些技术。
\nOAuth 2.0 是一种委托访问协议,允许应用程序在无需传递用户凭据的情况下获取对用户资源的有限访问权限。而 JWT 则是一种紧凑且自包含的令牌格式,常用于在客户端和服务器之间传递身份验证信息。
\n在本指南中,我们将使用 ASP.NET Core 创建一个简单的 Web API,实现基于 JWT 令牌的 OAuth 2.0。您将学习如何配置令牌生成、验证以及端点保护。
\n\n什么是 OAuth 2.0 和 JWT?
\n在进入代码之前,让我们先了解基本概念。
\nOAuth 2.0
\nOAuth 2.0 定义了四种角色:
\n- \n
- Resource Owner(资源所有者)——通常是用户。 \n
- Client(客户端)——想要获取访问权限的应用程序。 \n
- Authorization Server(授权服务器)——颁发令牌。 \n
- Resource Server(资源服务器)——提供受保护的数据。 \n
主要的 Authorization Code Grant(授权码授权)流程包括:将用户重定向到授权服务器、获取授权码、将授权码交换为访问令牌。
\n\nJWT(JSON Web Token)
\nJWT 由三部分组成,用点分隔:
\n- \n
- Header(头部)——令牌类型和签名算法(例如 HS256)。 \n
- Payload(负载)——数据(声明),如用户 ID、角色、过期时间。 \n
- Signature(签名)——使用密钥创建的签名。 \n
JWT 示例:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
ASP.NET Core 项目设置
\n让我们创建一个支持身份验证的新 Web API 项目。
\ndotnet new webapi -n OAuthJwtDemo\ncd OAuthJwtDemo\n添加必要的 NuGet 包:
\ndotnet add package Microsoft.AspNetCore.Authentication.JwtBearer\ndotnet add package System.IdentityModel.Tokens.Jwt\n\nappsettings.json 中的配置
\n在 appsettings.json 文件中添加 JWT 设置部分:
{\n "JwtSettings": {\n "SecretKey": "YOUR_SUPER_SECRET_KEY_AT_LEAST_32_CHARS",\n "Issuer": "OAuthJwtDemo",\n "Audience": "OAuthJwtDemoClient",\n "ExpirationMinutes": 60\n }\n}\n重要提示: 在实际项目中,请将密钥存储在 User Secrets 或 Azure Key Vault 中。
\n\n实现 JWT 生成服务
\n创建一个接口及其实现,用于处理令牌。
\nIJwtService 接口
\npublic interface IJwtService\n{\n string GenerateToken(string userId, string role);\n ClaimsPrincipal ValidateToken(string token);\n}\n\nJwtService 实现
\npublic class JwtService : IJwtService\n{\n private readonly JwtSettings _settings;\n\n public JwtService(IOptions<JwtSettings> settings)\n {\n _settings = settings.Value;\n }\n\n public string GenerateToken(string userId, string role)\n {\n var claims = new[]\n {\n new Claim(ClaimTypes.NameIdentifier, userId),\n new Claim(ClaimTypes.Role, role),\n new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())\n };\n\n var key = new Symmetric