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

相关推荐
成为大佬先秃头4 天前
开放标准(RFC 7519):JSON Web Token (JWT)
spring boot·后端·json·jwt
成为大佬先秃头4 天前
前后分离项目:整合JWT+Shiro
java·springboot·shiro·jwt
弹简特9 天前
【JavaEE34-博客系统案例实战】从零开始撸一个博客系统(二):登录 + JWT令牌 + 强制登录,让系统先有“门卫”
jwt·博客系统·java实战
indexsunny9 天前
互联网大厂Java面试实录:Spring Boot到微服务的深入探讨
java·spring boot·微服务·面试·eureka·kafka·jwt
弹简特10 天前
【JavaEE】JWT令牌:签名、密钥、生成令牌、校验令牌、编码、解码,一篇文章彻底讲透
jwt·密钥
庞轩px13 天前
JWT与Session比较
jwt·session·登录鉴权·无状态
庞轩px14 天前
JWT + Redis 双 Token 机制:从原理到实战
数据库·redis·缓存·jwt·token·登录认证
带娃的IT创业者15 天前
WeClaw_43_双重认证与Token自动刷新:Device Fingerprint与JWT安全机制
jwt·认证机制·双重认证·设备指纹·token刷新·http安全
૮・ﻌ・1 个月前
Node.js - 04:MongoDB、会话控制
数据库·mongodb·node.js·jwt·token·cookie·session
indexsunny1 个月前
互联网大厂Java面试实战:从Spring Boot到微服务架构的音视频场景解析
java·spring boot·spring cloud·mybatis·spring security·jwt·flyway