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

Angular17+ASP.NET Core8中JWT刷新时Audience重复追加问题

JWT刷新时Audience字段重复追加的问题解决

问题描述

我正在开发一个基于Angular 17前端、ASP.NET Core 8后端的Web应用,实现了包含Refresh Token(存储于数据库)的JWT认证功能。创建Token环节无异常,但每次执行Token刷新操作时,JWT中的Audience字段会持续重复追加相同值。多次刷新后,Audience数组如下:

{
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "[Removed]",
  "http://schemas.microsoft.com/ws/2008/06/identity/claims/role": "[Removed]",
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier": "[Removed]",
  "exp": 1718882692,
  "iss": "https://localhost:4200",
  "aud": [
    "https://localhost:4200",
    "https://localhost:4200",
    "https://localhost:4200",
    "https://localhost:4200",
    "https://localhost:4200",
    "https://localhost:4200",
    "https://localhost:4200",
    "https://localhost:4200",
    "https://localhost:4200"
  ]
}

原因分析

问题出在Token刷新流程的两个关键环节:

  1. 调用GetPrincipalFromExpiredToken验证过期Token后,返回的principal.Claims已经包含了原Token中的aud(audience)声明。
  2. 调用GenerateAccessToken生成新Token时,既传入了包含aud声明的claims集合,又在JwtSecurityToken构造函数中指定了audience参数。JWT处理逻辑会将这两个来源的audience合并,导致每次刷新都新增一个相同的audience值,最终形成重复数组。

解决方案

修改TokenService中的GenerateAccessToken方法,在传入claims时过滤掉已有的aud声明,避免重复添加:

public string GenerateAccessToken(IEnumerable<Claim> claims)
{
    var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
    var jwtSettings = _configuration.GetSection("JwtSettingsCommon");
    var environment = _configuration.GetSection("Production");
    if (env == "Development")
    {
        environment = _configuration.GetSection("Development");
    }
    var JwtSecret = jwtSettings["SigningKey"];
    var Issuer = environment["URI"];
    var Audience = environment["URI"];
    var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtSecret));
    var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);

    int expiry;
    try
    {
        expiry = Int32.Parse(jwtSettings["Expires"]);
    }
    catch (FormatException)
    {
        expiry = 10;
    }

    // 过滤掉claims中的aud声明,避免重复添加
    var filteredClaims = claims.Where(c => c.Type != JwtRegisteredClaimNames.Aud).ToList();

    var tokenOptions = new JwtSecurityToken(
        issuer: Issuer,
        audience: Audience,                
        claims: filteredClaims,
        expires: DateTime.Now.AddMinutes(expiry),
        signingCredentials: signinCredentials
    );
    var tokenString = new JwtSecurityTokenHandler().WriteToken(tokenOptions);
    return tokenString;
}

补充说明

  • JwtRegisteredClaimNames.Aud是系统定义的audience声明常量(值为"aud"),使用它比硬编码字符串更可靠。
  • 过滤操作确保新生成的Token中,audience仅来自构造函数指定的Audience参数,不会重复追加。

内容的提问来源于stack exchange,提问作者Jason Williams

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 03:37:32