在一个带有ASP.NET的RestAPI核心5项目中,我使用的是带有令牌和刷新-令牌的JWT。我将启动配置如下:
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,它抛出的异常没有指定的日期。
我尝试在启动时添加LifetimeValidator到TokenValidationParameters中,如下所示:
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:生存期验证失败。委托返回错误的安全令牌:'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'.
谢谢你的帮助
发布于 2021-12-07 21:55:31
我也有过类似的问题。我的服务器(生成令牌)时间和我的客户端(消耗令牌)时间是不同的。同步和完美地工作。
发布于 2022-11-19 03:55:14
在我的示例中,当我将应用程序部署到一个Linux服务器上时,出现了类似的"IDX10222“错误,原因是服务器当前时间运行在令牌创建时间之后,因此服务器无法验证令牌。
例如-令牌创建时间-10:00在dd:MM:yyyy,Linux服务器时间-08:00在dd:MM:yyyy
然后我们得到这个错误--生命周期验证失败。令牌尚未有效。
请检查您的计算机日期时间,并修复它是否与当前时间不同步。
发布于 2021-10-29 11:56:55
你试着:
/*
ClaimsPrincipal principal = null;
principal = jwtTokenHandler.ValidateToken(tokenRequest.Token, _tokenValidationParameters, out validatedToken);
*/
validatedToken = jwtTokenHandler.ReadJwtToken(token);
/*Your own validation logic*/
https://stackoverflow.com/questions/69217013
复制相似问题