为什么我的 JWT 不记名身份验证在令牌显示 5 分钟后将令牌识别为过期?
Why is my JWT bearer authentication recognizing tokens as expired 5 minutes after the token says?
我正在使用 AspNet.Security.OpenIdConnect.Server 颁发 JWT 令牌并将 AuthorizationCodeLifetime 设置为 30 秒以进行测试。这是我用来设置选项的代码片段
options.TokenEndpointPath = "/api/token";
options.AllowInsecureHttp = true;
options.AccessTokenHandler = new JwtSecurityTokenHandler();
options.SigningCredentials.Add(new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256));
options.AccessTokenLifetime = TimeSpan.FromSeconds(30);
options.AuthorizationCodeLifetime = TimeSpan.FromSeconds(30);
返回的令牌包含:
"expires_in": 30,
并且反序列化的令牌包含以下声明:
"nbf": 1476915220,
"exp": 1476915250,
"iat": 1476915220,
如您所见,exp(过期时间)比iat(发布时间)晚了30秒。然而,令牌在过期 5 分钟后才触发 401 Unauthorized。如果我们将 exp 数字插入 http://www.epochconverter.com/,那么我们将看到它的计算结果为 2016 年 10 月 19 日星期三 22:14:10 GMT,即我当地时间的 5:14:10 下午。
这是核心库的一些记录输出:
Microsoft.IdentityModel.Tokens.SecurityTokenExpiredException: IDX10223: Lifetime validation failed. The token is expired.
ValidTo: '10/19/2016 22:14:10'
Current time: '10/19/2016 22:19:10'.
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 securityToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.<HandleAuthenticateAsync>d__1.MoveNext()
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware[7]
Bearer was not authenticated. Failure message: IDX10223: Lifetime validation failed. The token is expired.
ValidTo: '10/19/2016 22:14:10'
Current time: '10/19/2016 22:19:10'.
当然,此输出并不能证明服务器正在接受 22:14:10 和 22:19:10 之间的令牌。如果我碰巧在它过期后等待 5 分钟然后尝试验证令牌,它就会这样做,但你必须相信我的话。我在 Postman 中进行测试,每秒点击 "Send",直到它返回 401。
所以,怎么了?是否内置了一些我不知道的 5 分钟缓冲区?有趣的是,AccessTokenLifetime 的默认值是 5 分钟,但令牌确实反映了我已将其更改为 30 秒。怎么回事?
我正在使用的相关库:
<package id="AspNet.Security.OpenIdConnect.Extensions" version="1.0.0-beta6-final" targetFramework="net452" />
<package id="AspNet.Security.OpenIdConnect.Server" version="1.0.0-beta6-final" targetFramework="net452" />
<package id="Microsoft.AspNetCore.Authentication.JwtBearer" version="1.0.0" targetFramework="net452" />
So, what's up? Is there some 5 minute buffer built in that I'm not aware of? What's going on?
你所说的"buffer"实际上是JWT承载中间件(由微软开发)提供的内置功能,被称为"clock skew",旨在减轻时钟不同步的影响在网络场中。
如您所想,the default value is set to 5 minutes, but it can be changed via JwtBearerOptions.TokenValidationParameters.ClockSkew
。
我试过 ClockSkew = TimeSpan.Zero:
new TokenValidationParameters
{
ClockSkew = TimeSpan.Zero
};
这是因为 ClockSkew 的默认值为 5 分钟
我正在使用 AspNet.Security.OpenIdConnect.Server 颁发 JWT 令牌并将 AuthorizationCodeLifetime 设置为 30 秒以进行测试。这是我用来设置选项的代码片段
options.TokenEndpointPath = "/api/token";
options.AllowInsecureHttp = true;
options.AccessTokenHandler = new JwtSecurityTokenHandler();
options.SigningCredentials.Add(new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256));
options.AccessTokenLifetime = TimeSpan.FromSeconds(30);
options.AuthorizationCodeLifetime = TimeSpan.FromSeconds(30);
返回的令牌包含:
"expires_in": 30,
并且反序列化的令牌包含以下声明:
"nbf": 1476915220,
"exp": 1476915250,
"iat": 1476915220,
如您所见,exp(过期时间)比iat(发布时间)晚了30秒。然而,令牌在过期 5 分钟后才触发 401 Unauthorized。如果我们将 exp 数字插入 http://www.epochconverter.com/,那么我们将看到它的计算结果为 2016 年 10 月 19 日星期三 22:14:10 GMT,即我当地时间的 5:14:10 下午。
这是核心库的一些记录输出:
Microsoft.IdentityModel.Tokens.SecurityTokenExpiredException: IDX10223: Lifetime validation failed. The token is expired.
ValidTo: '10/19/2016 22:14:10'
Current time: '10/19/2016 22:19:10'.
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 securityToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.<HandleAuthenticateAsync>d__1.MoveNext()
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware[7]
Bearer was not authenticated. Failure message: IDX10223: Lifetime validation failed. The token is expired.
ValidTo: '10/19/2016 22:14:10'
Current time: '10/19/2016 22:19:10'.
当然,此输出并不能证明服务器正在接受 22:14:10 和 22:19:10 之间的令牌。如果我碰巧在它过期后等待 5 分钟然后尝试验证令牌,它就会这样做,但你必须相信我的话。我在 Postman 中进行测试,每秒点击 "Send",直到它返回 401。
所以,怎么了?是否内置了一些我不知道的 5 分钟缓冲区?有趣的是,AccessTokenLifetime 的默认值是 5 分钟,但令牌确实反映了我已将其更改为 30 秒。怎么回事?
我正在使用的相关库:
<package id="AspNet.Security.OpenIdConnect.Extensions" version="1.0.0-beta6-final" targetFramework="net452" />
<package id="AspNet.Security.OpenIdConnect.Server" version="1.0.0-beta6-final" targetFramework="net452" />
<package id="Microsoft.AspNetCore.Authentication.JwtBearer" version="1.0.0" targetFramework="net452" />
So, what's up? Is there some 5 minute buffer built in that I'm not aware of? What's going on?
你所说的"buffer"实际上是JWT承载中间件(由微软开发)提供的内置功能,被称为"clock skew",旨在减轻时钟不同步的影响在网络场中。
如您所想,the default value is set to 5 minutes, but it can be changed via JwtBearerOptions.TokenValidationParameters.ClockSkew
。
我试过 ClockSkew = TimeSpan.Zero:
new TokenValidationParameters
{
ClockSkew = TimeSpan.Zero
};
这是因为 ClockSkew 的默认值为 5 分钟