如何读取已过期的JWT令牌

时间:2018-02-09 13:45:03

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

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

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

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

我的代码:

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令牌的用户名已过期或无效,我如何阅读该用户名?

1 个答案:

答案 0 :(得分: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应用程序在平均时间内重新启动并且您遇到令牌到期,我假设您正在使用临时签名密钥来签署JWT令牌。您应该切换到使用永久签名密钥。

对于您需要长期令牌的脱机客户端,请查看刷新令牌。刷新令牌通常具有更长的生命周期,可用于交换更新的访问令牌。指定范围offline_access时,标准oauth2.0实现问题刷新令牌。范围名称应指示刷新令牌的常见用例。

您可以将Web客户端和脱机客户端配置为Authority Server上的两个不同客户端,从而确保仅向脱机客户端发出刷新令牌。