You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core JWT能否实现无需存储的Refresh Token机制?

可以在ASP.NET Core JWT中实现无存储Refresh Token的机制

当然可以!你在ASP.NET Framework里实现的这种把用户身份信息和过期时间直接序列化到Refresh Token中、无需持久化存储的方案,完全可以在ASP.NET Core的JWT认证体系中复刻,核心思路和你原来的实现高度一致:将用户票据(包含身份信息和过期时间)直接编码进Refresh Token,验证时反序列化并检查有效性,同时刷新过期时间。

核心原理回顾

你原来的方案本质逻辑是:

  • 生成Refresh Token时,把包含用户身份和过期时间的AuthenticationTicket序列化后作为Token内容
  • 刷新Token时,反序列化这个Ticket,验证过期时间,然后重新设置过期时间并生成新的Refresh Token
  • 全程不需要将Token存到数据库或其他存储介质,所有必要信息都封装在Token本身里

ASP.NET Core中的实现步骤

下面是适配ASP.NET Core认证体系的完整代码实现:

1. 自定义Refresh Token处理服务

我们可以实现一个专门的服务来处理Refresh Token的生成、验证和刷新,对应你原来的Create和Receive方法逻辑:

using Microsoft.AspNetCore.Authentication;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

public class RefreshTokenService
{
    private readonly IConfiguration _configuration;

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

    // 生成Refresh Token:将用户身份票据序列化后转为Base64字符串
    public string GenerateRefreshToken(ClaimsPrincipal principal)
    {
        var refreshTokenExpiryDays = Convert.ToInt32(_configuration["Jwt:RefreshTokenExpiryDays"]);
        
        // 创建包含用户身份和过期时间的认证票据
        var ticket = new AuthenticationTicket(
            principal,
            new AuthenticationProperties
            {
                ExpiresUtc = DateTime.UtcNow.AddDays(refreshTokenExpiryDays),
                IsPersistent = true
            },
            JwtBearerDefaults.AuthenticationScheme);

        // 序列化票据为字节数组再转Base64(和Framework的SerializeTicket逻辑一致)
        var serializer = new TicketSerializer();
        var ticketBytes = serializer.Serialize(ticket);
        return Convert.ToBase64String(ticketBytes);
    }

    // 验证并刷新Refresh Token:反序列化票据、检查有效性、更新过期时间
    public AuthenticationTicket? ValidateAndRefreshToken(string refreshToken)
    {
        try
        {
            // 反序列化Token为认证票据
            var ticketBytes = Convert.FromBase64String(refreshToken);
            var serializer = new TicketSerializer();
            var ticket = serializer.Deserialize(ticketBytes);

            if (ticket == null)
                return null;

            // 检查Token是否已过期
            if (ticket.Properties.ExpiresUtc <= DateTime.UtcNow)
                return null;

            // 刷新Token的过期时间
            ticket.Properties.ExpiresUtc = DateTime.UtcNow.AddDays(Convert.ToInt32(_configuration["Jwt:RefreshTokenExpiryDays"]));
            
            return ticket;
        }
        catch
        {
            // 序列化/反序列化失败,返回null表示Token无效
            return null;
        }
    }
}

2. 配置认证服务与依赖注入

在Program.cs中注册自定义服务并配置JWT认证:

var builder = WebApplication.CreateBuilder(args);

// 注册RefreshTokenService到依赖注入容器
builder.Services.AddScoped<RefreshTokenService>();

// 配置JWT认证
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
        };
    });

var app = builder.Build();

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

// 其他中间件配置...

app.Run();

3. 实现刷新Token的API接口

添加一个API控制器来处理Refresh Token的刷新请求,对应你原来的ReceiveAsync逻辑:

using Microsoft.AspNetCore.Mvc;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

[ApiController]
[Route("api/auth")]
public class AuthController : ControllerBase
{
    private readonly RefreshTokenService _refreshTokenService;
    private readonly IConfiguration _configuration;

    public AuthController(RefreshTokenService refreshTokenService, IConfiguration configuration)
    {
        _refreshTokenService = refreshTokenService;
        _configuration = configuration;
    }

    [HttpPost("refresh-token")]
    public IActionResult RefreshToken([FromForm] string refreshToken)
    {
        if (string.IsNullOrEmpty(refreshToken))
            return BadRequest("Invalid refresh token");

        var ticket = _refreshTokenService.ValidateAndRefreshToken(refreshToken);
        if (ticket == null)
            return Unauthorized("Refresh token expired or invalid");

        // 生成新的Access Token
        var newAccessToken = GenerateAccessToken(ticket.Principal.Claims);
        // 生成新的Refresh Token
        var newRefreshToken = _refreshTokenService.GenerateRefreshToken(ticket.Principal);

        return Ok(new
        {
            AccessToken = newAccessToken,
            RefreshToken = newRefreshToken
        });
    }

    // 辅助方法:生成JWT格式的Access Token
    private string GenerateAccessToken(IEnumerable<Claim> claims)
    {
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
        var accessTokenExpiryMinutes = Convert.ToInt32(_configuration["Jwt:AccessTokenExpiryMinutes"]);

        var token = new JwtSecurityToken(
            issuer: _configuration["Jwt:Issuer"],
            audience: _configuration["Jwt:Audience"],
            claims: claims,
            expires: DateTime.UtcNow.AddMinutes(accessTokenExpiryMinutes),
            signingCredentials: creds);

        return new JwtSecurityTokenHandler().WriteToken(token);
    }
}

关键注意事项

  • 安全性:因为Refresh Token包含用户敏感身份信息,务必确保所有请求通过HTTPS传输,防止Token被拦截。另外,建议设置合理的Refresh Token过期时间,若用户修改密码等敏感信息,可通过缩短现有Token有效期来降低泄露风险(纯无存储方案无法直接失效旧Token,只能靠过期时间控制)。
  • Grant Type判断:你原代码中只在非refresh_token的授权类型下生成Refresh Token的逻辑,可以在登录接口中实现(比如用户使用密码登录时生成,刷新Token时仅验证后生成新Token)。
  • 序列化兼容性:ASP.NET Core的TicketSerializer和Framework的实现兼容,若你需要迁移旧系统,原有的Refresh Token可以直接在Core中验证。

内容的提问来源于stack exchange,提问作者Mubashir Khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:08:36