使用 System.IdentityModel.Tokens.Jwt 直接实现基于 JWT 的鉴权和授权,可以在 ASP.NET Core 中手动生成、解析、验证 JWT Token。System.IdentityModel.Tokens.Jwt 提供了 JWT 的生成和解析的 API。以下是如何使用该库实现鉴权授权的详细步骤。

步骤 1: 安装 NuGet 包

确保安装了以下包来使用 JWT:

dotnet add package System.IdentityModel.Tokens.Jwt

步骤 2: 生成 JWT Token

使用 JwtSecurityTokenHandler 来生成 JWT Token。一般情况下,会在用户登录成功后生成 Token 并返回给客户端。

生成 Token 的代码示例:
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

public class JwtTokenService
{
    private readonly IConfiguration _configuration;

    public JwtTokenService(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public string GenerateToken(string username)
    {
        // 从配置中读取密钥
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JwtSettings:Secret"]));
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        // 定义 Token 的声明(可以存储用户的标识信息)
        var claims = new[]
        {
            new Claim(JwtRegisteredClaimNames.Sub, username),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
            // 可以添加更多的自定义声明,如角色等
        };

        // 创建 Token
        var token = new JwtSecurityToken(
            issuer: _configuration["JwtSettings:Issuer"],
            audience: _configuration["JwtSettings:Audience"],
            claims: claims,
            expires: DateTime.Now.AddMinutes(120), // 设置过期时间
            signingCredentials: creds);

        // 生成 JWT 并返回
        return new JwtSecurityTokenHandler().WriteToken(token);
    }
}

步骤 3: 验证 JWT Token

客户端在请求时会携带 JWT Token(通常在 HTTP 请求的 Authorization 头中),服务器端需要验证 Token 的有效性。在验证 JWT 时,我们可以使用 JwtSecurityTokenHandler.ValidateToken 方法。

验证 Token 的代码示例:
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Text;

public class JwtTokenValidator
{
    private readonly IConfiguration _configuration;

    public JwtTokenValidator(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public ClaimsPrincipal ValidateToken(string token)
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = Encoding.UTF8.GetBytes(_configuration["JwtSettings:Secret"]);

        try
        {
            // 验证 Token 的参数设置
            var validationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidIssuer = _configuration["JwtSettings:Issuer"],
                ValidAudience = _configuration["JwtSettings:Audience"],
                ValidateLifetime = true, // 验证 Token 是否过期
                ClockSkew = TimeSpan.Zero // 不允许时间偏差
            };

            // 验证 Token 并返回解析后的 ClaimsPrincipal
            var principal = tokenHandler.ValidateToken(token, validationParameters, out SecurityToken validatedToken);

            // 验证通过返回解析后的 Token 信息
            return principal;
        }
        catch (Exception)
        {
            // 验证失败,返回 null
            return null;
        }
    }
}

步骤 4: 使用 JWT 鉴权授权

ASP.NET Core 中集成 JWT 鉴权时,通常会在 HTTP 请求的 Authorization 头中传递 Token,格式为 Bearer <Token>。如果你要手动处理 Token 的验证,可以在控制器或中间件中直接调用 JwtTokenValidator 类来验证 Token。

客户端请求的示例:
GET /api/protected/data HTTP/1.1
Host: yourdomain.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
在控制器中使用手动验证 Token:
[ApiController]
[Route("api/[controller]")]
public class ProtectedController : ControllerBase
{
    private readonly JwtTokenValidator _tokenValidator;

    public ProtectedController(JwtTokenValidator tokenValidator)
    {
        _tokenValidator = tokenValidator;
    }

    [HttpGet("data")]
    public IActionResult GetProtectedData()
    {
        var token = Request.Headers["Authorization"].ToString().Replace("Bearer ", "");

        // 验证 Token 的有效性
        var principal = _tokenValidator.ValidateToken(token);

        if (principal == null)
        {
            // Token 无效或验证失败
            return Unauthorized(new { message = "Invalid Token" });
        }

        // 返回受保护的数据
        return Ok(new { message = "This is protected data", user = principal.Identity.Name });
    }
}

步骤 5: 添加授权逻辑

在 JWT Token 中,可以加入自定义的 Claim,如角色或权限,之后根据这些 Claim 执行角色或权限的授权检查。

添加角色到 JWT:

在生成 JWT 时,可以添加角色到 Token 中:

var claims = new[]
{
    new Claim(JwtRegisteredClaimNames.Sub, username),
    new Claim(ClaimTypes.Role, "Admin"),  // 添加角色信息
    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
根据角色进行授权:

在验证 Token 后,你可以通过检查 ClaimsPrincipal 中的角色来决定是否授权用户访问某些资源。

public IActionResult GetAdminData()
{
    var token = Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
    var principal = _tokenValidator.ValidateToken(token);

    if (principal == null)
    {
        return Unauthorized(new { message = "Invalid Token" });
    }

    // 检查用户是否拥有 Admin 角色
    if (!principal.IsInRole("Admin"))
    {
        return Forbid(new { message = "You do not have access to this resource" });
    }

    // 返回管理员数据
    return Ok(new { message = "This is admin data" });
}

System.IdentityModel.Tokens.Jwt 提供了完整的 JWT 生成和验证功能,适用于手动处理 Token 逻辑的场景。

12-14 05:28