当前位置:首页 > C# > 正文

ASP.NET Core JWT刷新令牌详解(手把手教你实现安全的用户会话续期)

在现代Web应用开发中,ASP.NET Core JWT刷新令牌是保障用户会话安全、提升用户体验的重要机制。本文将从零开始,详细讲解如何在ASP.NET Core项目中实现JWT(JSON Web Token)身份验证,并加入刷新令牌功能,让小白开发者也能轻松上手。

为什么需要刷新令牌?

JWT通常包含一个较短的有效期(例如15分钟),以减少令牌被盗用的风险。但频繁让用户重新登录体验很差。因此,我们引入刷新令牌(Refresh Token):它是一个长期有效的令牌,用于在访问令牌过期后获取新的访问令牌,而无需用户重新输入账号密码。

ASP.NET Core JWT刷新令牌详解(手把手教你实现安全的用户会话续期) JWT刷新令牌 JWT身份验证 .NET Core安全认证 刷新令牌实现 第1张

准备工作

确保你已安装:

  • .NET 6 或更高版本 SDK
  • Visual Studio / VS Code / Rider
  • 基本的C#和ASP.NET Core知识

步骤一:创建ASP.NET Core Web API项目

打开终端,执行以下命令:

dotnet new webapi -n JwtRefreshTokenDemocd JwtRefreshTokenDemo

步骤二:安装必要NuGet包

在项目根目录运行:

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

步骤三:配置JWT认证服务

Program.cs 中添加以下代码:

using Microsoft.IdentityModel.Tokens;using System.Text;var builder = WebApplication.CreateBuilder(args);// 添加JWT认证builder.Services.AddAuthentication(options =>{    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;}).AddJwtBearer(options =>{    options.TokenValidationParameters = new TokenValidationParameters    {        ValidateIssuer = true,        ValidateAudience = true,        ValidateLifetime = true,        ValidateIssuerSigningKey = true,        ValidIssuer = builder.Configuration["Jwt:Issuer"],        ValidAudience = builderConfiguration["Jwt:Audience"],        IssuerSigningKey = new SymmetricSecurityKey(            Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!))    };});builder.Services.AddControllers();var app = builder.Build();app.UseAuthentication();app.UseAuthorization();app.MapControllers();app.Run();

并在 appsettings.json 中添加配置:

{  "Jwt": {    "Key": "ThisIsASecretKeyForDemoOnlyDoNotUseInProduction",    "Issuer": "https://localhost:5001",    "Audience": "https://localhost:5001"  }}

步骤四:创建用户模型与令牌服务

首先定义用户和令牌响应模型:

public class User{    public string Username { get; set; } = string.Empty;    public string Password { get; set; } = string.Empty;}public class AuthResponse{    public string AccessToken { get; set; } = string.Empty;    public string RefreshToken { get; set; } = string.Empty;    public DateTime AccessTokenExpiry { get; set; }    public DateTime RefreshTokenExpiry { get; set; }}

步骤五:实现JWT与刷新令牌生成逻辑

创建一个服务类 TokenService.cs

using Microsoft.IdentityModel.Tokens;using System.IdentityModel.Tokens.Jwt;using System.Security.Claims;using System.Text;public class TokenService{    private readonly IConfiguration _config;    public TokenService(IConfiguration config)    {        _config = config;    }    public (string accessToken, DateTime expiry) GenerateAccessToken(string username)    {        var tokenHandler = new JwtSecurityTokenHandler();        var key = Encoding.UTF8.GetBytes(_config["Jwt:Key"]!);        var tokenDescriptor = new SecurityTokenDescriptor        {            Subject = new ClaimsIdentity(new[]            {                new Claim(ClaimTypes.Name, username)            }),            Expires = DateTime.UtcNow.AddMinutes(15), // 短期有效            Issuer = _config["Jwt:Issuer"],            Audience = _config["Jwt:Audience"],            SigningCredentials = new SigningCredentials(                new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)        };        var token = tokenHandler.CreateToken(tokenDescriptor);        return (tokenHandler.WriteToken(token), token.ValidTo);    }    public (string refreshToken, DateTime expiry) GenerateRefreshToken()    {        var refreshToken = Guid.NewGuid().ToString();        var expiry = DateTime.UtcNow.AddDays(7); // 刷新令牌有效期7天        return (refreshToken, expiry);    }}

Program.cs 中注册服务:

builder.Services.AddSingleton();

步骤六:创建认证控制器

新建 AuthController.cs

[ApiController][Route("[controller]")]public class AuthController : ControllerBase{    private readonly TokenService _tokenService;    public AuthController(TokenService tokenService)    {        _tokenService = tokenService;    }    [HttpPost("login")]    public IActionResult Login([FromBody] User user)    {        // 简化:实际应验证数据库中的用户名密码        if (user.Username == "admin" && user.Password == "123456")        {            var (accessToken, accessExpiry) = _tokenService.GenerateAccessToken(user.Username);            var (refreshToken, refreshExpiry) = _tokenService.GenerateRefreshToken();            // 实际项目中应将刷新令牌存入数据库并关联用户            return Ok(new AuthResponse            {                AccessToken = accessToken,                RefreshToken = refreshToken,                AccessTokenExpiry = accessExpiry,                RefreshTokenExpiry = refreshExpiry            });        }        return Unauthorized();    }    [HttpPost("refresh")]    public IActionResult Refresh([FromBody] RefreshRequest request)    {        // 此处应验证refreshToken是否存在于数据库且未过期        // 为简化,此处跳过验证        var (accessToken, accessExpiry) = _tokenService.GenerateAccessToken("admin");        var (newRefreshToken, newRefreshExpiry) = _tokenService.GenerateRefreshToken();        return Ok(new AuthResponse        {            AccessToken = accessToken,            RefreshToken = newRefreshToken,            AccessTokenExpiry = accessExpiry,            RefreshTokenExpiry = newRefreshExpiry        });    }}public class RefreshRequest{    public string RefreshToken { get; set; } = string.Empty;}

安全提示

在生产环境中,务必:

  • 将刷新令牌存储在安全的数据库中,并绑定用户ID
  • 使用HTTPS传输所有令牌
  • 对刷新令牌设置合理的过期时间(如7-30天)
  • 实现令牌吊销机制(如登出时删除刷新令牌)

总结

通过本教程,你已掌握如何在ASP.NET Core JWT刷新令牌系统中实现安全的身份验证流程。这种模式广泛应用于现代API开发中,是.NET Core安全认证的最佳实践之一。记住,刷新令牌实现不仅要功能完整,更要注重安全性。

希望这篇关于JWT身份验证的教程对你有所帮助!如有疑问,欢迎留言交流。