1.自动续期
using **.**.Common.Helper;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
namespace **.**.Login.Extensions
{
public static class JwtTokenSetup
{
public static void AddJwtTokenSetup(this IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,//是否验证Issuer
ValidateAudience = true,//是否验证Audience
ValidateLifetime = true,//是否验证失效时间
ValidateIssuerSigningKey = true,//是否验证SecurityKey
ClockSkew = TimeSpan.Zero,
ValidAudience = Appsettings.app(new string[] { "Authentication", "Audience" }),//Audience
ValidIssuer = Appsettings.app(new string[] { "Authentication", "Issuer" }),//Issuer,这两项和前面签发jwt的设置一致
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Appsettings.app(new string[] { "Authentication", "SecretKey" })))//拿到SecurityKey
};
options.Events = new JwtBearerEvents
{
OnTokenValidated = context =>
{
var claimsIdentity = context.Principal.Identity as ClaimsIdentity;
if (claimsIdentity != null)
{
// 检查 token 的过期时间
var expClaim = claimsIdentity.FindFirst(JwtRegisteredClaimNames.Exp);
if (expClaim != null)
{
var exp = long.Parse(expClaim.Value);
var expirationTime = DateTimeOffset.FromUnixTimeSeconds(exp).UtcDateTime;
var remainingTime = expirationTime - DateTime.UtcNow;
// 如果剩余时间少于5分钟,则生成新的 token
if (remainingTime < TimeSpan.FromMinutes(5))
{
var newToken = GenerateNewToken(claimsIdentity.Claims);
context.Response.Headers.Add("Token-Expired", "true");
context.Response.Headers.Add("New-Token", newToken);
}
}
}
return Task.CompletedTask;
},
//权限验证失败后执行
OnChallenge = context =>
{
//终止默认的返回结果(必须有)
context.HandleResponse();
var result = "{\"success\":false,\"code\":\"-1\",\"msg\":\"\",\"obj\":{\"message\":\"Token not provided\",\"status\":\"401\"}}";//JsonConvert.SerializeObject(new { success = false, code = 401, msg = "Token timeout", obj = "" });
context.Response.ContentType = "application/json";
//验证失败返回401
context.Response.StatusCode = StatusCodes.Status200OK;
context.Response.WriteAsync(result);
return Task.FromResult(0);
}
};
});
}
private static string GenerateNewToken(IEnumerable<Claim> claims)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Appsettings.app(new string[] { "Authentication", "SecretKey" })));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: Appsettings.app(new string[] { "Authentication", "Issuer" }),
audience: Appsettings.app(new string[] { "Authentication", "Audience" }),
claims: claims,
expires: DateTime.Now.AddMinutes(Convert.ToInt32(Appsettings.app(new string[] { "Authentication", "Lifetime" }))), // 令牌有效期(例如30分钟)
signingCredentials: creds);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
}