目录
一、打开nuget,搜索JWT,安装最新版到对应的使用层即可 1
1、 JWT依赖包
2、 JWT的认证授权扩展包、Microsoft.AspNetCore.Authentication.JwtBearer版本
(注:这里使用的是 .NET 6,所以 JWT的认证授权扩展包安装的版本是6开头的)
二、创建JWT相关的帮助类
1、JwtHelper帮助类
public static class JwtHelper
{
/// <summary>
/// 生成token令牌
/// </summary>
/// <param name="claimInfo"></param>
/// <param name="tokenManagement"></param>
/// <returns></returns>
public static string CreateToken(Claim[] claimInfo, TokenManagement tokenManagement)
{
//1、获取TokenManagement类中的Secret字符串
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenManagement.Secret));
//2、key加密方式
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
//3、生成token的时间
var notTime = DateTimeHelper.GetThisDateTime(); //开始时间
//4、token过期时间
var expiresTime = notTime.AddMinutes(tokenManagement.AccessExpiration); //到期时间
//5、生成token的配置信息
var jwtToken = new JwtSecurityToken(tokenManagement.Issuer, tokenManagement.Audience, claimInfo, notTime, expiresTime, credentials);
string token = new JwtSecurityTokenHandler().WriteToken(jwtToken);
return token;
}
/// <summary>
/// 获取请求上下文Claims中的UserId
/// </summary>
/// <param name="httpContext">请求上下文</param>
/// <returns></returns>
public static string GetUserId(HttpContext httpContext)
{
string userId = "";
if (httpContext.User is null)
return userId;
if (!httpContext.User.Claims.Any())
return userId;
var claim = httpContext.User.Claims.FirstOrDefault(e => e.Type == ClaimTypes.Sid);
if (claim is null)
return userId;
userId = claim.Value;
return userId;
}
/// <summary>
/// 获取请求上下文Claims中的Name名称
/// </summary>
/// <param name="httpContext">请求上下文</param>
/// <returns></returns>
public static string GetName(HttpContext httpContext)
{
string name = "";
if (httpContext.User is null)
return name;
if (!httpContext.User.Claims.Any())
return name;
var claim = httpContext.User.Claims.FirstOrDefault(e => e.Type == ClaimTypes.Name);
if (claim is null)
return name;
name = claim.Value;
return name;
}
/// <summary>
/// 解析token获取JwtSecurityToken对象
/// </summary>
/// <param name="token">token</param>
/// <returns></returns>
public static JwtSecurityToken GetSecurityToken(string token)
{
token = GetRemoveBearerToken(token);
//解析token
JwtSecurityToken jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(token);
return jwtToken;
}
/// <summary>
/// 获取token中存储的信息
/// </summary>
/// <param name="httpContext">http数据上下文</param>
/// <returns></returns>
public static TokenPayload GetTokenPayload(HttpContext httpContext)
{
var token = GetRemoveBearerToken(httpContext.Request.Headers["Authorization"].ToString());
//解析token
JwtSecurityToken jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(token);
//获取token中的payload信息
TokenPayload tokenPayload = new TokenPayload()
{
Id = Convert.ToInt32(jwtToken.Payload[ClaimTypes.Sid]),
Email = jwtToken.Payload[ClaimTypes.Email].ToString(),
UserName = jwtToken.Payload[ClaimTypes.Surname].ToString(),
Name = jwtToken.Payload[ClaimTypes.Name].ToString(),
Role = jwtToken.Payload[ClaimTypes.Role].ToString(),
};
return tokenPayload;
}
/// <summary>
/// 获取token中存储的信息
/// </summary>
/// <param name="token">token令牌</param>
/// <returns></returns>
public static TokenPayload GetTokenPayload(string token)
{
token = GetRemoveBearerToken(token);
//解析token
JwtSecurityToken jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(token);
//获取token中的payload信息
TokenPayload tokenPayload = new TokenPayload()
{
Id = Convert.ToInt32(jwtToken.Payload[ClaimTypes.Sid]),
Email = jwtToken.Payload[ClaimTypes.Email].ToString(),
UserName = jwtToken.Payload[ClaimTypes.Surname].ToString(),
Name = jwtToken.Payload[ClaimTypes.Name].ToString(),
};
if (jwtToken.Payload[ClaimTypes.Role] != null)
tokenPayload.Role = jwtToken.Payload[ClaimTypes.Role].ToString();
return tokenPayload;
}
/// <summary>
/// 获取去除字符串开头Bearer的token令牌
/// </summary>
/// <param name="token">token令牌</param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public static string GetRemoveBearerToken(string token)
{
if (token.IsNullOrEmpty())
throw new ArgumentNullException("传入的token为空!");
if (token.StartsWith("Bearer "))
return token.Replace("Bearer ", "");
return token;
}
}
2、创建TokenManagement类,存储JWT相关的配置信息
/// <summary>
/// 存储Jwt配置信息
/// </summary>
public class TokenManagement
{
/// <summary>
/// 令牌密钥
/// </summary>
[JsonProperty("secret")]
public string Secret { get; set; } = null!;
/// <summary>
/// 颁发者
/// </summary>
[JsonProperty("issuer")]
public string? Issuer { get; set; }
/// <summary>
/// 接收者
/// </summary>
[JsonProperty("audience")]
public string? Audience { get; set; }
/// <summary>
/// Token令牌过期时间(分钟)
/// </summary>
[JsonProperty("accessExpiration")]
public int AccessExpiration { get; set; }
/// <summary>
/// Token刷新令牌过期时间(分钟)
/// </summary>
[JsonProperty("refreshExpiration")]
public int RefreshExpiration { get; set; }
}
3、创建TokenPayload类,用于存储我们的payload信息
/// <summary>
/// 存储、解析生成Token要用到的信息
/// </summary>
public class TokenPayload
{
/// <summary>
/// 编号
/// </summary>
public long Id { get; set; }
/// <summary>
/// 名称
/// </summary>
public string? Name { get; set; }
/// <summary>
/// 邮箱
/// </summary>
public string? Email { get; set; }
/// <summary>
/// 用户名
/// </summary>
public string? UserName { get; set; }
/// <summary>
/// 角色
/// </summary>
public string? Role { get; set; }
}
三、appsestting.json配置文件,配置JWT过期等密钥信息
//JwtTokenManagement参数
"TokenManagement": {
"secret": "8630EAA6-CB86-413F-D925-08DC525AFD88", //"密钥",
"issuer": "longNight", //签发
"audience": "longNightClient", //接收
"accessExpiration": 120, //过期分钟数,2小时过期
}
四、在Program中配置JWT相关信息
#region Jwt配置
//读取Jwt配置信息
var jwtSection = builder.Configuration.GetSection("TokenManagement");
//Jwt配置信息,注入配置中
builder.Services.Configure<TokenManagement>(jwtSection);
TokenManagement tokenManagement = jwtSection.Get<TokenManagement>();
//Jwt鉴权配置
builder.Services.AddAuthorization(options => { }).AddAuthentication(options =>
{
//2.1【认证】、core自带官方JWT认证
// 开启Bearer认证
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true, //是否验证SecurityKey
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(tokenManagement.Secret)), //这里的key要进行加密
//验证发布者Issuer
ValidateIssuer = true,
ValidIssuer = tokenManagement.Issuer, //Token颁发机构
//验证接收者
ValidateAudience = true,
ValidAudience = tokenManagement.Audience, //颁发给谁
ValidateLifetime = true, //验证token过期时间
ClockSkew = TimeSpan.FromSeconds(30), //时钟缓冲相位差
RequireExpirationTime = true, //token需要设置过期时间
};
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
// 如果过期,则把<是否过期>添加到,返回头信息中
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{
context.Response.Headers.Add("Token-Expired", "true");
}
return Task.CompletedTask;
}
};
});
#endregion
记录学习时刻↩︎