安全令牌过期异常:IDX10223:生命周期验证失败。该令牌已过期。有效期至:'System.DateTime',当前时间:'System.DateTime'。 SecurityTokenExpiredException: IDX10223: Lifetime validation failed. The token is expired. ValidTo: 'System.DateTime', Current time: 'System.DateTime'.

7
在一个使用RestAPI的ASP.NET Core 5项目中,我正在使用JWT Bearer以及tokens和refresh-tokens。我像这样配置了启动项:
var jwtSecretKey = Configuration.GetValue<string>("Jwt:Key");
var key = Encoding.UTF8.GetBytes(jwtSecretKey);

var tokenValidationParameters = new TokenValidationParameters
{
    SaveSigninToken = true,
    ValidateActor = true,
    ValidateIssuer = true,
    ValidateAudience = true,
    ValidateLifetime = true,
    ValidateIssuerSigningKey = true,
    ValidIssuer = Configuration["Jwt:Issuer"],
    ValidAudience = Configuration["Jwt:Audience"],
    IssuerSigningKey = new SymmetricSecurityKey(key),
    // set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
    ClockSkew = TimeSpan.Zero
};

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

生成令牌时,我使用了以下代码(需要注意的是,我使用了UTC日期):
string validIssuer = _configuration["Jwt:Issuer"];
string validAudience = _configuration["Jwt:Audience"];
var jwtSecretKey = _configuration.GetValue<string>("Jwt:Key");
var issuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSecretKey));
var accessTimeout = _configuration.GetValue<int>("Jwt:MinutosExpiracionTokenAcceso");

DateTime fechaHoy = DateTime.UtcNow;
DateTime fechaExpiracionToken = DateTime.UtcNow.AddMinutes(accessTimeout);

var userRoles = await _userManager.GetRolesAsync(user);

var claims = new List<Claim>
{
    new Claim(ClaimTypes.Sid, user.Id),
    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) // (JWT ID) Unique Identifier for JWT, can be used to prevent the JWT from being replayed. Is best suited for refresh tokens
};

foreach (var userRole in userRoles)
{
    claims.Add(new Claim(ClaimTypes.Role, userRole));
}

var token = new JwtSecurityToken(
    validIssuer,
    validAudience,
    claims,
    fechaHoy,
    fechaExpiracionToken,
    new SigningCredentials(issuerSigningKey, SecurityAlgorithms.HmacSha256)
);

var refreshTimeout = _configuration.GetValue<int>("Jwt:MinutosExpiracionTokenAutorizacion");

var refreshToken = new RefreshToken()
{
    JwtId = token.Id,
    IsUsed = false,
    UserId = user.Id,
    AddedDate = DateTime.UtcNow,
    ExpiryDate = DateTime.UtcNow.AddMinutes(refreshTimeout),
    IsRevoked = false,
    Token = RandomString(25) + Guid.NewGuid()
};

await _unitOfWork.GetRepository<RefreshToken>().AddAsync(refreshToken);
await _unitOfWork.SaveChangesAsync();

var tokensDto = new TokensResponseDto
{
    Token = new JwtSecurityTokenHandler().WriteToken(token),
    RefreshToken = refreshToken.Token
};

return tokensDto;

我遇到了验证令牌的问题(_tokenValidationParameters与启动时使用的相同):

var jwtTokenHandler = new JwtSecurityTokenHandler();
ClaimsPrincipal principal = null;
SecurityToken validatedToken = null;

principal = jwtTokenHandler.ValidateToken(tokenRequest.Token, _tokenValidationParameters, out validatedToken);

无论我使用本地时间如DateTime.Now还是UTC,都会抛出没有特定日期的上述异常。

我试过在启动时像这样在TokenValidationParameters中添加LifetimeValidator:

LifetimeValidator = (DateTime? notBefore, 
                     DateTime? expires, 
                     SecurityToken securityToken, 
                     TokenValidationParameters validationParameters
                    ) => 
                    {
                        if (expires != null)
                        {
                            if (DateTime.UtcNow < expires.Value.ToUniversalTime())
                            {
                                return true; // Still valid
                            }
                        }

                        return false; // Expired
                    }

然而,ValidateToken会出现以下异常:

IDX10230: 生命周期验证失败。委托返回false,securitytoken: 'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'。

感谢任何帮助。
3个回答

2

我有一个类似的问题。我的服务器(生成令牌)时间和客户端(消耗令牌)时间不同步。同步后完美解决了。


0
在我的情况中,当我将应用程序部署到Linux服务器之一时,出现了类似的"IDX10222"错误。这个错误背后的原因是服务器当前时间落后于令牌创建时间,所以服务器无法验证该令牌。
例如 - 令牌创建时间 - UTC dd:MM:yyyy 的10:00:00, Linux服务器时间 - UTC dd:MM:yyyy 的08:00:00
然后我们会收到此错误 - 寿命验证失败。 令牌尚未有效。
请检查您机器的日期时间,并修复如果它与当前时间不同步的问题。

-1

你来试试:

/*
ClaimsPrincipal principal = null;
principal = jwtTokenHandler.ValidateToken(tokenRequest.Token, _tokenValidationParameters, out validatedToken);
*/

validatedToken = jwtTokenHandler.ReadJwtToken(token);

/*Your own validation logic*/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接