.NET Core JWT 认证实现流程

1. 理解 JWT 认证

在开始实现 .NET Core JWT 认证之前,我们首先需要了解什么是 JWT 认证。JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络中传输信息的一种基于 JSON 的简洁、自包含的安全性较高的方式。JWT 由三部分组成:头部、载荷和签名,它们使用 Base64 编码进行传输。

  • 头部(Header):包含算法和令牌类型(如 JWT)。
  • 载荷(Payload):包含一些声明(例如,用户 ID、过期时间等)。
  • 签名(Signature):使用密钥对头部和载荷进行签名,以验证数据的完整性和真实性。

JWT 认证的流程如下:

stateDiagram
    [*] --> 用户登录
    用户登录 --> 生成 JWT 令牌: 使用用户凭证生成 JWT 令牌
    生成 JWT 令牌 --> 返回令牌: 将令牌返回给用户
    返回令牌 --> 用户请求: 用户使用令牌进行请求
    用户请求 --> 验证令牌: 验证令牌的有效性
    验证令牌 --> 验证成功: 令牌有效,继续处理请求
    验证令牌 --> 验证失败: 令牌无效,返回错误信息
    验证成功 --> 处理请求
    验证失败 --> 返回错误信息

2. 实现步骤

下面是实现 ".NET Core JWT 认证" 的步骤:

步骤 描述
1 添加 NuGet 包
2 配置 JWT 选项
3 创建身份验证服务
4 创建 Token 生成器
5 创建 Token 验证器
6 配置身份验证中间件

3. 代码实现

3.1 添加 NuGet 包

首先,我们需要添加以下 NuGet 包到项目中:

```powershell
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

#### 3.2 配置 JWT 选项

在 `appsettings.json` 文件中添加 JWT 相关配置:

```json
{
  "JwtOptions": {
    "Issuer": "your_issuer",
    "Audience": "your_audience",
    "Key": "your_secret_key"
  }
}

Startup.cs 文件中的 ConfigureServices 方法中,添加 JWT 选项的配置:

public void ConfigureServices(IServiceCollection services)
{
    // ...

    var jwtOptions = Configuration.GetSection("JwtOptions").Get<JwtOptions>();
    services.Configure<JwtOptions>(Configuration.GetSection("JwtOptions"));

    // ...
}

3.3 创建身份验证服务

创建一个 JwtAuthenticationService 类,实现 IJwtAuthenticationService 接口,用于生成和验证 JWT 令牌。

public interface IJwtAuthenticationService
{
    string GenerateToken(string userId);
    bool ValidateToken(string token);
}

public class JwtAuthenticationService : IJwtAuthenticationService
{
    private readonly JwtOptions _jwtOptions;

    public JwtAuthenticationService(IOptions<JwtOptions> jwtOptions)
    {
        _jwtOptions = jwtOptions.Value;
    }

    public string GenerateToken(string userId)
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = Encoding.ASCII.GetBytes(_jwtOptions.Key);
        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(new[] { new Claim("userId", userId) }),
            Expires = DateTime.UtcNow.AddMinutes(_jwtOptions.ExpirationMinutes),
            Issuer = _jwtOptions.Issuer,
            Audience = _jwtOptions.Audience,
            SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
        };
        var token = tokenHandler.CreateToken(tokenDescriptor);
        return tokenHandler.WriteToken(token);
    }

    public bool ValidateToken(string token)
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = Encoding.ASCII.GetBytes(_jwtOptions.Key);
        try
        {
            tokenHandler.ValidateToken(token, new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidIssuer = _jwtOptions.Issuer,
                ValidAudience = _jwtOptions.Audience,
                IssuerSigningKey =