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

ASP.NET Core 8.0 JWT验证异常:有效令牌触发SecurityTokenNoExpirationException

ASP.NET Core 8.0 Web API JWT验证异常问题求助

问题概述

我正在开发一个分层架构的ASP.NET Core 8.0 Web API项目,这套JWT生成与验证逻辑迁移自已稳定运行3年的ASP.NET Core 6.0项目,服务器环境和配置未变,但在认证和注册端点的JWT验证过程中出现异常。调用GetPrincipalFromToken方法时提示令牌缺少过期时间,移除过期日期并禁用过期验证后,又会出现颁发者(issuer)和受众(audience)验证失败问题。但生成的令牌经jwt.io验证,exp、iss等字段均正确,怀疑问题与包版本或ValidateToken的处理逻辑有关。

Program.cs中的JWT验证参数配置

var tokenValidationParameters = new TokenValidationParameters()
{
    ValidateIssuer = true,
    ValidateAudience = true,
    ValidAudience = jwtSettings.ValidAudience,
    ValidIssuer = jwtSettings.ValidIssuer,
    IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtSettings.Secret)),
    ClockSkew = jwtSettings.TokenLifetime
};

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    options.SaveToken = true;
    options.RequireHttpsMetadata = false;
    options.TokenValidationParameters = tokenValidationParameters;

    options.Events = new JwtBearerEvents
    {
        OnMessageReceived = context =>
        {
            context.Token = context.Request.Cookies["authorization"];
            return Task.CompletedTask;
        }
    };
});

builder.Services.AddSingleton(tokenValidationParameters);

令牌生成方法

public async Task<Response<RefreshTokenDto>> GenerateAuthResultForCustomAsync(Customer customer)
{
    try
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = Encoding.ASCII.GetBytes(_jwtSettings.Secret);

        var userRoles = await _userManager.GetRolesAsync(customer);

        var authClaims = new List<Claim>
        {
            new Claim(JwtRegisteredClaimNames.Sub, customer.Email),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
            new Claim("customerId", customer.Id),
            new Claim("firstName", customer.FirstName),
            new Claim("lastName", customer.LastName),
            new Claim("countryId", customer.CountryId.ToString()),
            new Claim("phoneNumber", customer.PhoneNumber),
            new Claim("userName", customer.UserName)
        };

        authClaims.AddRange(userRoles.Select(role => new Claim(ClaimTypes.Role, role)));

        var tokenDescriptor = new SecurityTokenDescriptor()
        {
            Subject = new ClaimsIdentity(authClaims),
            Issuer = _jwtSettings.ValidIssuer,
            Audience = _jwtSettings.ValidAudience,
            Expires = _dateTimeProvider.Now.Add(_jwtSettings.TokenLifetime).UtcDateTime,
            SigningCredentials = new SigningCredentials(
                                  new SymmetricSecurityKey(key),
                                  SecurityAlgorithms.HmacSha256Signature)
        };

        var token = tokenHandler.CreateToken(tokenDescriptor);

        // 原代码返回逻辑未完整展示,此处省略
    }
    catch
    {
        // 原代码异常处理逻辑未完整展示,此处省略
    }
}

令牌验证方法

public class PrincipalTokenService : IPrincipalTokenService
{
    private readonly TokenValidationParameters _tokenValidationParameters;

    public PrincipalTokenService(TokenValidationParameters tokenValidationParameters)
    {
        _tokenValidationParameters = tokenValidationParameters;
    }

    public ClaimsPrincipal GetPrincipalFromToken(string token)
    {
        var tokenHandler = new JwtSecurityTokenHandler();

        try
        {
            var handler = tokenHandler.ValidateToken(
                token,
                _tokenValidationParameters,
                out var validatedToken);

            return !IsJwtWithValid(validatedToken) ? null : handler;
        }
        catch
        {
            return null;
        }
    }

    // 原代码IsJwtWithValid方法实现未展示,此处省略
}

异常信息

Microsoft.IdentityModel.Tokens.SecurityTokenNoExpirationException: 'IDX10225: Lifetime validation failed. The token is missing an Expiration Time. Tokentype: 'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'

项目相关包版本

<PackageReference Include="Asp.Versioning.Mvc" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.3">
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.3" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="7.4.1" />

补充说明

  • jwtSettings是从配置文件填充验证参数的模型
  • 即使硬编码验证参数,仍会出现相同问题
  • 生成的令牌在jwt.io上显示所有必填字段均正确

有没有人遇到过ASP.NET Core 8.0中的类似JWT验证问题?求指点或建议。


内容的提问来源于stack exchange,提问作者Levan Amashukeli

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 13:10:54