JWT
一.概述
JWT 在前后端项目中 保护API
三部分组成{
1头部:令牌的类型(JWT)和所使用的签名算法
载荷:(JSON): 主体内容(非敏感信息)
签名:使用指定的算法对头部、载荷以及密钥进行签名,确保令牌在传输过程中不被篡改
}
下包
二.实现
1.配置Program
//用于访问当前 HTTP 请求的上下文信息
builder.Services.AddHttpContextAccessor();
//注册JWT
//JWT认证
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
//取出私钥
var secretByte = Encoding.UTF8.GetBytes(builder.Configuration["JwtSettings:SecretKey"]);
options.TokenValidationParameters = new TokenValidationParameters()
{
//验证发布者
ValidateIssuer = true,
ValidIssuer = builder.Configuration["JwtSettings:Issuer"],
//验证接收者
ValidateAudience = true,
ValidAudience = builder.Configuration["JwtSettings:Audience"],
//验证是否过期
ValidateLifetime = true,
//验证私钥
IssuerSigningKey = new SymmetricSecurityKey(secretByte)
};
});
//鉴权中间件
app.UseAuthentication();
//授权中间件
app.UseAuthorization();
2.生成Token
public class TokenHelper
{
//读appsetings.json配置文件用的
private readonly IConfiguration _configuration;
//JwtSecurityTokenHandler 用来生成和验证JwtToken
private readonly JwtSecurityTokenHandler _jwtSecurityTokenHandler;
public TokenHelper(IConfiguration configuration, JwtSecurityTokenHandler jwtSecurityTokenHandler)
{
_configuration = configuration;
_jwtSecurityTokenHandler = jwtSecurityTokenHandler;
}
/// <summary>
/// 创建加密JwtToken
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public string CreateJwtToken<T>(T user)
{
//设置加密算法类型
var signingAlogorithm = SecurityAlgorithms.HmacSha256;
//加载载荷用户信息
var claimList = this.CreateClaimList(user);
//Signature
//取出私钥并以utf8编码字节输出
var secretByte = Encoding.UTF8.GetBytes(_configuration["JwtSettings:SecretKey"]);
//使用非对称算法对私钥进行加密
var signingKey = new SymmetricSecurityKey(secretByte);
//使用HmacSha256来验证加密后的私钥生成数字签名
var signingCredentials = new SigningCredentials(signingKey, signingAlogorithm);
//生成Token
var Token = new JwtSecurityToken(
issuer: _configuration["JwtSettings:Issuer"], //发布者
audience: _configuration["JwtSettings:Audience"], //接收者
claims: claimList, //存放的用户信息
notBefore: DateTime.UtcNow, //发布时间
expires: DateTime.UtcNow.AddDays(1), //有效期设置为1天
signingCredentials //数字签名
);
//生成字符串token
var TokenStr = new JwtSecurityTokenHandler().WriteToken(Token);
return TokenStr;
}
public T GetToken<T>(string Token)
{
Type t = typeof(T);
object objA = Activator.CreateInstance(t);
var b = _jwtSecurityTokenHandler.ReadJwtToken(Token);
foreach (var item in b.Claims)
{
PropertyInfo _Property = t.GetProperty(item.Type);
if (_Property != null && _Property.CanRead)
{
_Property.SetValue(objA, item.Value, null);
}
}
return (T)objA;
}
/// <summary>
/// 创建包含用户信息的CalimList
/// </summary>
/// <param name="authUser">User</param>
/// <returns></returns>
private List<Claim> CreateClaimList<T>(T authUser)
{
//获取用户数据类型
var Class = typeof(T);
//返回List 载荷信息
List<Claim> claimList = new List<Claim>();
//Class.GetProperties() 获取数据类型的所有属性
foreach (var item in Class.GetProperties())
{
//获取属性名称 item.Name
//获取属性值 item.GetValue(authUser) 转成 string
claimList.Add(new Claim(item.Name, Convert.ToString(item.GetValue(authUser))));
}
return claimList;
}
}
3.登录方法(成功 赋值Token)
/// <summary>
/// 登录
/// </summary>
/// <param name="userName">用户名</param>
/// <param name="password">密码</param>
/// <returns></returns>
[AllowAnonymous]
[HttpGet]
public IActionResult Login(string userName, string password)
{
var obj = _userService.Login(userName, password);
//传参过去的 实体
var token = _tokenHelper.CreateJwtToken(obj.userInfo);
return Ok(new
{
obj.code,
obj.msg,
obj.userId,
obj.userInfo,
obj.userName,
token
});
}
4.为了方便项目发布 随时修改秘钥等,必要信息放在配置文件里
"JwtSettings": {
"SecretKey": "sldkjfsdoifjweoifjweoifjwoeijfoweij", // 密钥Key 必须16位以上
"Issuer": "http://localhost:5000", // 发行人
"Audience": "http://localhost:5000/api" // 受众
}
5.Swagger添加JWT
//添加SwaggerUI
builder.Services.AddSwaggerGen(a =>
{
#region 开启Swagger认证
a.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
Description = "在下框中输入请求头中需要添加Jwt授权Token:Bearer Token",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
BearerFormat = "JWT",
Scheme = "Bearer"
});
a.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference {
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] { }
}
});
#endregion
});
注入
//注入TokenHelper
builder.Services.AddScoped(typeof(TokenHelper));
builder.Services.AddScoped(typeof(JwtSecurityTokenHandler));
或者在 AUTOMapper中
builder.RegisterType<JwtSecurityTokenHandler>();
builder.RegisterType<TokenHelper>();
封装Axios
import axios from "axios";
const instance = axios.create({
// 调用的api地址
//baseURL: "http://localhost:35891/",
timeout: 50000,
});
//添加请求拦截器
instance.interceptors.request.use(
function (config) {
if (sessionStorage.getItem('token') != null) {
config.headers.Authorization = `Bearer ${sessionStorage.getItem('token')}`;
}
return config;
}
);
//导出对象/实例
export default instance;