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;
posted @ 2024-06-27 09:58  Twolp  阅读(10)  评论(0编辑  收藏  举报