ASP .NET Core 8结合JWT轻松实现身份验证和授权

发布于:2025-07-16 ⋅ 阅读:(16) ⋅ 点赞:(0)

身份验证和授权是每一个后端服务必不可少的,可以实现对非法请求进行拦截,能够有效保护数据的安全性。

JSON Web Token(JWT)是一项开放标准(RFC 7519),它定义了一种紧凑且自包含的方法,用于以 JSON 对象的形式在各方之间安全地传递信息。这些信息经过数字签名,因此可以被验证和信任。

JWT官网文档:JSON Web Token Introduction - jwt.io

一、配置身份验证和授权

1、添加身份验证和JWT授权库

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

dotnet add package Microsoft.IdentityModel.Tokens

2、添加JWT配置信息到appsettings.json文件中

"JwtTokenConfig": {
  "Secret": "T#cx^Q$qsd8UrJMnY1(Vz$iie~lA3jgB96drYoPP4IDOffds&Qrw6GG+HClJteU#$)^JzMN_it#o*WE+*qVhE(_Ryy_t)",
  "Issuer": "http://www.my.com/",
  "Audience": "http://www.my.com/",
  "AccessTokenExpiration": 240
}

3、创建JwtTokenConfig信息类

public class JwtTokenConfig
{
    public string Secret { get; set; } = string.Empty;

    public string Issuer { get; set; } = string.Empty;

    public string Audience { get; set; } = string.Empty;

    public int AccessTokenExpiration { get; set; }
}

4、启用身份验证和JWT授权服务

 var builder = WebApplication.CreateBuilder(args);

JwtTokenConfig? jwtTokenConfig = builder.Configuration.GetSection("JwtTokenConfig").Get<JwtTokenConfig>();
if (jwtTokenConfig != null)
{
    builder.Services.AddSingleton(jwtTokenConfig);
    builder.Services.AddAuthentication(x =>
    {
        x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    }).AddJwtBearer(x =>
    {
        x.RequireHttpsMetadata = true;
        x.SaveToken = true;
        x.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuer = jwtTokenConfig.Issuer,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtTokenConfig.Secret)),
            ValidAudience = jwtTokenConfig.Audience,
            ValidateAudience = true,
            ValidateLifetime = true,
            ClockSkew = TimeSpan.FromMinutes(1)
        };
    });
}

var app = builder.Build();

5、显示注册身份验证和授权

var app = builder.Build();

app.UseCors();
app.UseAuthentication();
app.UseAuthorization();

app.MapGet("/", () => "Hello World!");
app.Run();

注:身份验证中间件是在 CORS 中间件运行后运行的,所以需要显示注册身份验证和授权

6、在控制器基类中添加授权特性,对所有控制器施加授权验证

[Route("api/[controller]/[action]")]
[ApiController]
[Authorize]
public abstract class BaseController : ControllerBase
{

}

二、生成JWT授权码

1、添加身份验证和JWT授权库

dotnet add package System.IdentityModel.Tokens.Jwt

dotnet add package Microsoft.IdentityModel.Tokens

2、创建JWT授权服务接口


public interface IJwtAuthService
{
    string GenerateJwtToken(Claim[] claims);
}

3、创建JWT授权服务业务逻辑

public class JwtAuthService : IJwtAuthService
{
    private readonly JwtTokenConfig _jwtTokenConfig;

    public JwtAuthService(JwtTokenConfig jwtTokenConfig)
    {
        _jwtTokenConfig = jwtTokenConfig;
    }

    public string GenerateJwtToken(Claim[] claims)
    {
        bool shouldAddAudienceClaim = string.IsNullOrWhiteSpace(claims?.FirstOrDefault(x => x.Type == JwtRegisteredClaimNames.Aud)?.Value);
        JwtSecurityToken jwtToken = new(
            _jwtTokenConfig.Issuer,
            shouldAddAudienceClaim ? _jwtTokenConfig.Audience : string.Empty,
            claims,
            expires: DateTime.Now.AddMinutes(_jwtTokenConfig.AccessTokenExpiration),
            signingCredentials: new SigningCredentials(new SymmetricSecurityKey(_secret), SecurityAlgorithms.HmacSha256Signature));
        return new JwtSecurityTokenHandler().WriteToken(jwtToken);
        
    }
}

4、注册JWT授权服务

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton<IJwtAuthService, JwtAuthService>();

var app = builder.Build();

5、在授权控制器中使用JWT服务,生成Token


public class AuthController : BaseController
{
    private readonly IJwtAuthService _authService;

    public AuthController(IAuthService authService)
    {
        _authService = authService;
    }

    [AllowAnonymous]
    [HttpPost]
    public IActionResult Login([FromBody] LoginRequest request)
    {
        // 1. 验证用户名密码(伪代码)
        if (!IsValidUser(request.User, request.Password))
            return Unauthorized();
        
        // 2. 创建JWT声明(伪代码)
        string roleName = "User";
        Claim[] claims =
        [
            new Claim(ClaimTypes.NameIdentifier, user),
            new Claim(ClaimTypes.Role, roleName)
        ];

        // 3. 生成 JWT Token
        var token = _authService.GenerateJwtToken(claims);

        // 4. 返回 Token
        return Ok(new { Token = token });
    }

    private bool IsValidUser(string user, string password)
    {
        // 实际应该查数据库(伪代码)
        return user == "admin" && password == "123456";
    }
}

注:使用ClaimTypes.NameIdentifier来声明用户标识,可以在集成SignalR时使SignalR很容易获取到用户标识并进行消息发送,因为SignalR默认获取的用户标识就是ClaimTypes.NameIdentifier


网站公告

今日签到

点亮在社区的每一天
去签到