【问题标题】:How to refresh the JWT in net core?如何在 net core 中刷新 JWT?
【发布时间】:2018-09-12 00:44:02
【问题描述】:

我有一种方法来验证用户并创建一个具有过期时间的令牌,但如果令牌过期,用户将无法使用数据。如何处理?

这是我的方法:

[AllowAnonymous]
[HttpPost]
[Route("api/token")]
public IActionResult Post([FromBody]Personal personal)
{
  string funcionID = "";
  if (ModelState.IsValid)
  {
    var userId = GetUser(personal);
    if (!userId.HasValue)
    {
      return Unauthorized();
    }
    else if (userId.Equals(2)) {
      return StatusCode(404, "Vuelve a ingresar tu contraseña");
    }

    List<Claim> claims = new List<Claim>();
    foreach (var funcion in Funcion) {
      claims.Add(new Claim(ClaimTypes.Role, funcion.FuncionID.ToString()));
    }

    claims.Add(new Claim(JwtRegisteredClaimNames.Email, personal.CorreoE));
    claims.Add(new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()));
    var sesionExpira = new DatabaseConfig();
    _configuration.GetSection("Database").Bind(sesionExpira);
  var token = new JwtSecurityToken
    (
        issuer: _configuration["Issuer"],
        audience: _configuration["Audience"],
        claims: claims,
        expires: DateTime.UtcNow.AddMinutes(sesionExpira.Sesion),
        notBefore: DateTime.UtcNow,
        signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["SigningKey"])),
             SecurityAlgorithms.HmacSha256)
    );
    var token_email = token.Claims.Where(w => w.Type == "email").Select(s => s.Value).FirstOrDefault();
    var token_rol = claims.Where(x => x.Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/role").Select(s => s.Value).FirstOrDefault();

    var nombre = _context.Personal.Where(x => x.CorreoE == personal.CorreoE).Select(x => x.Nombre).FirstOrDefault();
    return Ok(new { email = personal.CorreoE, token = new JwtSecurityTokenHandler().WriteToken(token), nombre = nombre, funcion = Funcion});

  }
  return BadRequest();
}

首先,在返回 int 的 GetUser(Personal personal) 方法中,我返回一个用于创建新令牌的数字。一切正常,但如果时间已过,我需要一些信息来刷新令牌

【问题讨论】:

  • 只生成一个新令牌。

标签: c# asp.net-core jwt


【解决方案1】:

您可以创建将更新令牌的中间件。如果您将令牌创建逻辑移至单独的服务,那么您可以这样做:

public class JwtTokenSlidingExpirationMiddleware
{
    private readonly RequestDelegate next;
    private readonly ITokenCreationService tokenCreationService;

    public JwtTokenSlidingExpirationMiddleware(RequestDelegate next, ITokenCreationService tokenCreationService)
    {
        this.next = next;
        this.tokenCreationService= tokenCreationService;
    }

    public Task Invoke(HttpContext context)
    {
        // Preflight check 1: did the request come with a token?
        var authorization = context.Request.Headers["Authorization"].FirstOrDefault();
        if (authorization == null || !authorization.ToLower().StartsWith("bearer") || string.IsNullOrWhiteSpace(authorization.Substring(6)))
        {
            // No token on the request
            return next(context);
        }

        // Preflight check 2: did that token pass authentication?
        var claimsPrincipal = context.Request.HttpContext.User;
        if (claimsPrincipal == null || !claimsPrincipal.Identity.IsAuthenticated)
        {
            // Not an authorized request
            return next(context);
        }

        // Extract the claims and put them into a new JWT
        context.Response.Headers.Add("Set-Authorization", tokenCreationService.CreateToken(claimsPrincipal.Claims));

        // Call the next delegate/middleware in the pipeline
        return next(context);
    }
}

并在 Startup.cs 中注册:

public void Configure(IApplicationBuilder app)
{
    ...
    app.UseMiddleware<JwtTokenSlidingExpirationMiddleware>();
    ...
}

【讨论】:

  • 为了让它对我正常工作,我必须将创建服务的 DI 移动到 Invoke() 方法 - 因为我使用的 Scoped 服务也用于其他类。另外值得注意的是,UseMiddleware() 必须在 UseAuthentication 之后进行,并且在我的情况下,必须立即在它之后进行 - 更下面将无法正常工作。
【解决方案2】:

我使用来自 IdentityModel 的 RefreshTokenAsync 方法做了一些与旧应用程序类似的事情。

当用户未经授权时,您可以尝试这样的事情:

var identityService = await DiscoveryClient.GetAsync("http://localhost:5000");
// request token
var tokenClient = new TokenClient(identityService.TokenEndpoint, "client", "secret");
var tokenResponse = await tokenClient.RequestRefreshTokenAsync(refreshToken);                     
return Ok(new { success = true, tokenResponse = tokenResponse });

来源:https://github.com/IdentityModel/IdentityModel.OidcClient.Samples/issues/4

编辑:我已根据规则编辑了我的原始答案以提供更清晰和更好的答案。

【讨论】:

    猜你喜欢
    • 2018-03-30
    • 2021-01-17
    • 2018-02-20
    • 2018-01-04
    • 2017-10-12
    • 2015-10-26
    • 2018-09-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多