【问题标题】:How to read a JWT token that has expired如何读取已过期的 JWT 令牌
【发布时间】:2018-07-20 07:25:41
【问题描述】:

我在我的 ASP.NET Core 2 Web API 项目中使用 JWT 令牌

我的前端 Web 客户端发送一个 JWT 令牌,它最初从 Web API 登录 API 获得,每个请求都能正常工作。但是,我也有一个离线客户端,它使用相同的 API 并最初在线登录,然后存储 JWT 离线发送,仅当用户同步应用程序时才发送它,这可能是一周后。令牌可能已过期或服务器 Web 应用程序在此期间重新启动。

如果 JWT 令牌由于离线客户端过期而失败,我仍然希望访问 Web API 控制器方法并填充 ASP.NET Identity User 对象,因为我需要用户名。我将记录此事件,但我也需要过期/无效令牌中的用户名。目前,如果身份验证失败,将不会输入控制器方法,因此我添加了一个 [AllowAnonymous] 属性,但这将导致 User.Identity 在我想要用户名的地方为空

我的代码:

Startup.cs

    public void ConfigureServices(IServiceCollection services)
    {

        services.AddAuthentication()
            .AddJwtBearer(cfg =>
            {
                cfg.TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidIssuer = _config["Tokens:Issuer"],
                    ValidAudience = _config["Tokens:Audience"],
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Tokens:Key"]))
                };

            });

当用户登录时

   private IActionResult CreateToken(ApplicationUser user, IList<string> roles)
    {
        var claims = new List<Claim>
        {
          new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()),
          new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
          new Claim(JwtRegisteredClaimNames.UniqueName, user.UserName)
        };



        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Tokens:Key"]));

        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        var token = new JwtSecurityToken(
          _config["Tokens:Issuer"],
          _config["Tokens:Audience"],
          claims.ToArray(),
         expires: DateTime.Now.AddMinutes(60),
          signingCredentials: creds);

        var results = new
        {
            token = new JwtSecurityTokenHandler().WriteToken(token),
            expiration = token.ValidTo,
        };

        return Created("", results);

我确保在经过身份验证后,各种 API 调用都会传递 JWT 令牌。

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
 public class MyController : Controller
{

这使我可以使用以下代码捕获登录用户以进行各种 API 调用

 var loggedInUser = User.Identity.Name;

如果 JWT 令牌已过期或无效,我如何读取用户名?

【问题讨论】:

    标签: asp.net-core jwt asp.net-core-webapi


    【解决方案1】:

    如果您希望即使令牌已过期也能通过授权,您只需将其添加到TokenValidationParameters 即可禁用生命周期验证

    services.AddAuthentication()
            .AddJwtBearer(cfg =>
            {
                cfg.TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidIssuer = _config["Tokens:Issuer"],
                    ValidAudience = _config["Tokens:Audience"],
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Tokens:Key"]))
    
                    //Do not check the expiry of token
                    ValidateLifetime = false,
                };
    
            });
    

    这将确保授权中间件认为令牌有效,并在 MVC 中间件中填充 User.Identity 对象。

    但是,此检查也会禁用您的 Web 客户端的到期检查。您将必须确定合适的客户端(不能绝对完成)并检查控制器中的到期时间。

    更好的方法是寻找更好的设计来解决您的基本需求。

    令牌可能已过期或服务器 Web 应用在此期间重新启动

    我对这个说法有点困惑。如果服务器 Web 应用程序同时重新启动并且您遇到令牌到期,我假设您正在使用临时签名密钥来签署 JWT 令牌。您应该改用永久签名密钥。

    对于需要长期令牌的离线客户端,请查看刷新令牌。刷新令牌通常具有更长的生命周期,并且可用于将自身交换为更新的访问令牌。指定范围 offline_access 时,标准 oauth2.0 实现会发出刷新令牌。范围名称应指明刷新令牌的常见用例。

    您可以在您的授权服务器上将 Web 客户端和离线客户端配置为两个不同的客户端,从而确保仅向离线客户端颁发刷新令牌。

    【讨论】:

      猜你喜欢
      • 2019-08-08
      • 1970-01-01
      • 2021-12-24
      • 1970-01-01
      • 2021-12-31
      • 2017-03-04
      • 2019-07-04
      • 2019-09-28
      • 2020-02-20
      相关资源
      最近更新 更多