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

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

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

相关推荐
ん贤5 小时前
JWT基础详解
开发语言·go·jwt
quweiie4 天前
tp8.0\jwt接口安全验证
前端·安全·jwt·thinkphp
百锦再12 天前
服务器间接口安全问题的全面分析
运维·服务器·安全·api·jwt·token·net
ArabySide13 天前
【WCF】通过AOP实现基于JWT的授权与鉴权的实践
c#·jwt·aop·wcf
ZHOU_WUYI1 个月前
flask JWT 认证
后端·flask·jwt
小小工匠1 个月前
每日一博 - JWT 安全实战指南
安全·jwt
FungLeo1 个月前
NodeJS Koa 后端用户会话管理,JWT, Session,长短Token,本文一次性讲明白
jwt·token·session·会话管理·cookies
14L1 个月前
互联网大厂Java面试:从Spring Cloud到Kafka的技术考察
spring boot·redis·spring cloud·kafka·jwt·oauth2·java面试
失败尽是常态Z2 个月前
基于JWT+Redis的登录流程实现
java·数据库·redis·状态模式·jwt·用户登录