当前位置: 首页 > 知识库问答 >
问题:

JwtSecurityToken不会在应该过期的时候过期

亢正德
2023-03-14

我目前正在系统中使用JwtSecurityToken类。标识模型。令牌命名空间。我使用以下内容创建令牌:

DateTime expires = DateTime.UtcNow.AddSeconds(10);
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
var genericIdentity = new System.Security.Principal.GenericIdentity(username, "TokenAuth");

ClaimsIdentity identity = new ClaimsIdentity(claims);
string secret = ConfigurationManager.AppSettings["jwtSecret"].ToString();
var securityKey = new     InMemorySymmetricSecurityKey(Encoding.Default.GetBytes(secret));
var signingCreds = new SigningCredentials(securityKey,     SecurityAlgorithms.HmacSha256Signature, SecurityAlgorithms.HmacSha256Signature);
var securityToken = handler.CreateToken(
    issuer: issuer,
    audience: ConfigurationManager.AppSettings["UiUrl"].ToString(),
    signingCredentials: signingCreds,
    subject: identity,
    expires: expires,
    notBefore: DateTime.UtcNow
);
return handler.WriteToken(securityToken); 

出于某种原因,即使过期时间设置为当前时间后10秒,当令牌被验证到大约5分钟时,它实际上不会引发异常。看到这个后,我想可能有5分钟的最低过期时间,所以我将过期时间设置为:

DateTime.UtcNow.AddMinutes(5);

然后,它将在10分钟后过期,但异常消息表示过期时间设置为应该的时间(用户登录后5分钟),当它在异常中显示当前时间时,则为过期时间后5分钟。所以,它似乎知道它应该在什么时候过期,但实际上直到过期时间过后5分钟才抛出异常。然后,由于令牌似乎在我设置的到期时间的基础上增加了5分钟,我将到期时间设置为:

DateTime.UtcNow.AddMinutes(-5).AddSecond(10);

我测试了这个,到目前为止它还没有过期(十多分钟后)。有人能解释一下为什么会这样,我做错了什么吗?此外,如果您看到我提供的代码中的任何其他内容,我们将不胜感激,因为我还不熟悉使用JWTs和这个库。

共有3个答案

屠泰平
2023-03-14

LifeTimeValidator似乎存在一些问题。只需使用自定义委托重写其逻辑即可。此外,还可以使用JWTBeareOptions类来控制身份验证中间件的行为。例如:

new JwtBearerOptions
{
     AutomaticAuthenticate = true,
     AutomaticChallenge = true,
     TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
     {
           ValidIssuer = _configuration["Tokens:Issuer"],
           ValidAudience = _configuration["Tokens:Audience"],
           ValidateIssuer = true,
           ValidateAudience = true,
           ValidateLifetime = true,
           LifetimeValidator = LifetimeValidator,
           ValidateIssuerSigningKey = true,
           IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Tokens:Key"]))
      }
}

并分配LifetimeValidotor委托,以提供自己的超时验证逻辑:

private bool LifetimeValidator(DateTime? notBefore, DateTime? expires, SecurityToken token, TokenValidationParameters @params)
{
     if (expires != null)
     {
          return expires > DateTime.UtcNow;
     }
     return false;
}
宰父学
2023-03-14

通读@Denis Kucherov的答案后,我发现我可以使用他发布的相同自定义验证器,而无需使用JwtBearerOptions类,这需要我添加一个新库。

此外,由于有两个名称空间包含许多相同的类,我将确保提及所有这些都在使用该系统。识别模型。。。名称空间。(不是Microsoft.IdentityModels…)

以下是我最终使用的代码:

private bool CustomLifetimeValidator(DateTime? notBefore, DateTime? expires, SecurityToken tokenToValidate, TokenValidationParameters @param)
{
    if (expires != null)
    {
        return expires > DateTime.UtcNow;
    }
    return false;
}
private JwtSecurityToken ValidateJwtToken(string tokenString)
{
   string secret = ConfigurationManager.AppSettings["jwtSecret"].ToString();
   var securityKey = new InMemorySymmetricSecurityKey(Encoding.Default.GetBytes(secret));
   JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
   TokenValidationParameters validation = new TokenValidationParameters()
   {
       ValidAudience = "MyAudience",
       ValidIssuer = "MyIssuer",
       ValidateIssuer = true,
       ValidateLifetime = true,
       LifetimeValidator = CustomLifetimeValidator,
       RequireExpirationTime = true,
       IssuerSigningKey = securityKey,
       ValidateIssuerSigningKey = true,
   };
   SecurityToken token;
   ClaimsPrincipal principal = handler.ValidateToken(tokenString, validation, out token);
   return (JwtSecurityToken)token;
}
王棋
2023-03-14

问题与ClockSkew有关。通常,验证库(至少是MS库)会补偿时钟偏移<代码>时钟偏移默认值为5分钟。看到答案了吗

您可以在TokenValidationParameters中更改ClockSkew

var tokenValidationParameters = new TokenValidationParameters
{
    //...your setting

    // set ClockSkew is zero
    ClockSkew = TimeSpan.Zero
};

app.UseJwtBearerAuthentication(new JwtBearerOptions
{
    AutomaticAuthenticate = true,
    AutomaticChallenge = true,
    TokenValidationParameters = tokenValidationParameters
});

快乐编码!

 类似资料:
  • 就在我以为我已经明白的时候...*叹息* 从我读到的关于立即的所有信息来看,我希望有以下几点: > 当尝试执行foo而不为输入字段提供值时,不会执行该操作,因为在期间发生错误,导致在此阶段之后直接重新呈现页面并显示错误消息。的值保持不变。(按预期工作) 当尝试do bar而不为输入字段提供值时,由于immediate属性,该操作将在期间执行。变量已更改。(按预期工作) “null返回值(作为act

  • 我在Tomcat7中有一个web应用程序,它将会话中的用户信息作为DTO对象保存。我还为我的项目启用了Spring Security性,如果用户没有会话,它会自动将用户重定向到登录页面。 如果我登录到应用程序一次,然后在Eclipse中重新启动Tomcat,会发生的情况是,我的会话被冲出,但cookie没有运行。 Edit:尽管Firefox说,但如果关闭并重新启动Firefox,cookie仍然

  • 问题内容: 我正在尝试使用 BufferedReader 通过URL上的InputStreamReader 从Web文档中读取文本(到某些Apache服务器上的文件)。 现在,这很好。但是显然,我希望读者不要只读一行,而应该读文件中的所有行。 查看BufferedReader API,以下代码应做到这一点: 即在有更多行时读取所有行,在没有更多行时停止。但是,此代码不起作用-读者 永远不会 报告

  • 问题内容: 我知道他们两个都禁用了Nagle的算法。 我什么时候应该/不应该使用它们中的每一个? 问题答案: 首先,不是所有人都禁用Nagle的算法。 Nagle的算法用于减少有线中更多的小型网络数据包。该算法是:如果数据小于限制(通常是MSS),请等待直到收到先前发送的数据包的ACK,同时累积用户的数据。然后发送累积的数据。 这将对telnet等应用程序有所帮​​助。但是,在发送流数据时,等待A

  • 问题内容: 在该类中,有两个字符串,和。 有什么不同?我什么时候应该使用另一个? 问题答案: 如果你的意思是和则: 用于在文件路径列表中分隔各个文件路径。考虑在上的环境变量。您使用a分隔文件路径,因此在上将是;。 是或用于拆分到特定文件的路径。例如在上,或

  • 问题内容: 我有一个会话验证过滤器,当会话过期时该过滤器注销用户。 这是一段代码,但是没有用。不起作用意味着即使会话过期,它也不会重定向到登录页面。 请帮助我解决此问题。 问题答案: 我有一个会话验证过滤器,当会话过期时该过滤器注销用户。 老实说,这完全没有道理。如果将已登录用户存储为会话的属性,并基于会话中已登录用户的存在来拦截“已登录”状态,则在任何时候都不需要手动注销该用户。会话已过期。当会