Web API 访问令牌过期后未刷新
Web API access token not refreshing after it's expired
访问令牌有效时我可以刷新它,但是过期后我就不能再刷新了。我和他有完全相同的问题但是我没有找到任何解决方案。
这就是我生成访问令牌的方式:
public async Task<string> GenerateAccessToken(User _User)
{
var userId = _User.Id.ToString();
var userName = _User.UserName;
var claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, userId),
new Claim(ClaimTypes.Name, userName)
};
var roles = await _userManager.GetRolesAsync(_User);
foreach (var role in roles) claims.Add(new Claim(ClaimTypes.Role, role));
var secret = "";
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = DateTime.Now.AddMinutes(10),
SigningCredentials = creds
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
经过一些调试我发现这个函数给我错误:
public ClaimsPrincipal GetPrincipalFromExpiredToken(string _Token)
{
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
ValidateLifetime = true,
RequireExpirationTime = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("")),
ValidateIssuer = false,
ValidateAudience = false
};
IdentityModelEventSource.ShowPII = true;
var tokenHandler = new JwtSecurityTokenHandler();
SecurityToken securityToken;
var principal = tokenHandler.ValidateToken(_Token, tokenValidationParameters, out securityToken);
var jwtSecurityToken = securityToken as JwtSecurityToken;
if (jwtSecurityToken == null || !jwtSecurityToken.Header.Alg.Equals("hs256", StringComparison.InvariantCultureIgnoreCase))
throw new SecurityTokenException("Invalid token");
return principal;
}
更具体地说,这一行
var principal = tokenHandler.ValidateToken(_Token, tokenValidationParameters, out securityToken);
我尝试刷新时收到以下响应:
Microsoft.IdentityModel.Tokens.SecurityTokenExpiredException: IDX10223: Lifetime validation failed. The token is expired. ValidTo: '04/25/2022 13:28:11', Current time: '04/25/2022 15:06:26'.
at Microsoft.IdentityModel.Tokens.Validators.ValidateLifetime(Nullable`1 notBefore, Nullable`1 expires, SecurityToken securityToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateLifetime(Nullable`1 notBefore, Nullable`1 expires, JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateTokenPayload(JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
at rentalAppAPI.BLL.Helper.TokenHelper.GetPrincipalFromExpiredToken(String _Token) in C:\Users\Alex\source\repos\rentalAppAPI\rentalAppAPI.BLL\Helper\ITokenHelper.cs:line 86
at rentalAppAPI.BLL.Managers.AuthManager.Refresh(RefreshModel refreshModel) in C:\Users\Alex\source\repos\rentalAppAPI\rentalAppAPI.BLL\Managers\AuthManager.cs:line 83
at rentalAppAPI.Controllers.AuthController.Refresh(RefreshModel model) in C:\Users\Alex\source\repos\rentalAppAPI\rentalAppAPI\Controllers\AuthController.cs:line 45
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
我在这个错误后查找
SecurityTokenExpiredException Class
Throw this exception when a received Security Token has expiration time in the past.
把ValidateLifetime = true,
改成false
,如果还是不行,把RequireExpirationTime
也改成false
。
在您的 var tokenValidationParameters = new TokenValidationParameters{}
中,您将验证生命周期设置为 true,这意味着当您尝试刷新有效访问令牌时,令牌可以被解码并将 return 主体正确,但是当您尝试刷新过期的访问令牌时,由于令牌已过期,因此无法对其进行解码。
当我们编写刷新逻辑时,我们需要将 ValidateAudience, ValidateIssuer, ValidateLifetime, RequireExpirationTime
保持为 false 以便我们无论如何都可以解码访问令牌...
访问令牌有效时我可以刷新它,但是过期后我就不能再刷新了。我和他有完全相同的问题
这就是我生成访问令牌的方式:
public async Task<string> GenerateAccessToken(User _User)
{
var userId = _User.Id.ToString();
var userName = _User.UserName;
var claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, userId),
new Claim(ClaimTypes.Name, userName)
};
var roles = await _userManager.GetRolesAsync(_User);
foreach (var role in roles) claims.Add(new Claim(ClaimTypes.Role, role));
var secret = "";
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = DateTime.Now.AddMinutes(10),
SigningCredentials = creds
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
经过一些调试我发现这个函数给我错误:
public ClaimsPrincipal GetPrincipalFromExpiredToken(string _Token)
{
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
ValidateLifetime = true,
RequireExpirationTime = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("")),
ValidateIssuer = false,
ValidateAudience = false
};
IdentityModelEventSource.ShowPII = true;
var tokenHandler = new JwtSecurityTokenHandler();
SecurityToken securityToken;
var principal = tokenHandler.ValidateToken(_Token, tokenValidationParameters, out securityToken);
var jwtSecurityToken = securityToken as JwtSecurityToken;
if (jwtSecurityToken == null || !jwtSecurityToken.Header.Alg.Equals("hs256", StringComparison.InvariantCultureIgnoreCase))
throw new SecurityTokenException("Invalid token");
return principal;
}
更具体地说,这一行
var principal = tokenHandler.ValidateToken(_Token, tokenValidationParameters, out securityToken);
我尝试刷新时收到以下响应:
Microsoft.IdentityModel.Tokens.SecurityTokenExpiredException: IDX10223: Lifetime validation failed. The token is expired. ValidTo: '04/25/2022 13:28:11', Current time: '04/25/2022 15:06:26'.
at Microsoft.IdentityModel.Tokens.Validators.ValidateLifetime(Nullable`1 notBefore, Nullable`1 expires, SecurityToken securityToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateLifetime(Nullable`1 notBefore, Nullable`1 expires, JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateTokenPayload(JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
at rentalAppAPI.BLL.Helper.TokenHelper.GetPrincipalFromExpiredToken(String _Token) in C:\Users\Alex\source\repos\rentalAppAPI\rentalAppAPI.BLL\Helper\ITokenHelper.cs:line 86
at rentalAppAPI.BLL.Managers.AuthManager.Refresh(RefreshModel refreshModel) in C:\Users\Alex\source\repos\rentalAppAPI\rentalAppAPI.BLL\Managers\AuthManager.cs:line 83
at rentalAppAPI.Controllers.AuthController.Refresh(RefreshModel model) in C:\Users\Alex\source\repos\rentalAppAPI\rentalAppAPI\Controllers\AuthController.cs:line 45
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
我在这个错误后查找 SecurityTokenExpiredException Class
Throw this exception when a received Security Token has expiration time in the past.
把ValidateLifetime = true,
改成false
,如果还是不行,把RequireExpirationTime
也改成false
。
在您的 var tokenValidationParameters = new TokenValidationParameters{}
中,您将验证生命周期设置为 true,这意味着当您尝试刷新有效访问令牌时,令牌可以被解码并将 return 主体正确,但是当您尝试刷新过期的访问令牌时,由于令牌已过期,因此无法对其进行解码。
当我们编写刷新逻辑时,我们需要将 ValidateAudience, ValidateIssuer, ValidateLifetime, RequireExpirationTime
保持为 false 以便我们无论如何都可以解码访问令牌...