当前位置: 首页 > article >正文

从0到1搭建权限管理系统系列三 .net8 JWT创建Token并使用

创建Token

创建token的因素(条件)有很多,在该篇文章中,采用jwt配置和用户基本信息作为生成token的基本因素(读者可根据系统,自由改变生成token因素)。

在JwtPlugInUnit.CS中创建2个方法(JwtPlugInUnit.CS在上一篇文章中有写到)

方法一:PropValuesType方法

/// <summary>
/// 反射获取字段
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static IEnumerable<(string Name, object Value, string Type)> PropValuesType(this object obj)
{
    List<(string a, object b, string c)> result = new List<(string a, object b, string c)>();

    var type = obj.GetType();
    var props = type.GetProperties();
    foreach (var item in props)
    {
        result.Add((item.Name, item.GetValue(obj), item.PropertyType.Name));
    }
    return result;
}

上述方法:PropValuesType是通过反射获取模型字段和属性。在本文章中,是为了提取登录人员信息,编写成List<Claim>,组成生成token的因素之一。

方法二:BuildToken方法

/// <summary>
/// 生成Token
/// </summary>
/// <param name="loginResult">登陆返回信息</param>
/// <returns></returns>
public static LoginOutPut BuildToken(LoginInput loginResult)
{
    LoginOutPut result = new LoginOutPut();
    //获取配置
    var jwtsetting = AppSettingsPlugInUnit.GetNode<JwtSettingModel>("JwtSetting");

    //准备calims,记录登录信息
    var calims = loginResult.PropValuesType().Select(x => new Claim(x.Name, x.Value.ToString(), x.Type)).ToList();

    //创建header
    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtsetting.SecurityKey));
    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
    var header = new JwtHeader(creds);

    //创建payload
    var payload = new JwtPayload(jwtsetting.Issuer, jwtsetting.Audience, calims, DateTime.Now, DateTime.Now.AddMinutes(jwtsetting.ExpireSeconds));

    //创建令牌 
    var token = new JwtSecurityToken(header, payload);
    var tokenStr = new JwtSecurityTokenHandler().WriteToken(token);
    result.ExpiresDate = token.ValidTo.AddHours(8).ToString();
    result.Token = tokenStr;
    result.UserName = loginResult.UserName;

    return result;
}

上述方法:BuildToken是创建token的核心代码,它通过用户信息+jwt配置信息生成token,并返回token、用户名、token过期时间等信息(读者可以添加更多返回信息)。

BuildToken中有2个模型,具体结构和位置如下:

创建Model类,用于存放系统中模型。

LoginInput模型结构如下:

/// <summary>
/// 登录输入模型
/// </summary>
public class LoginInput
{
    /// <summary>
    /// 用户名
    /// </summary>
    public string? UserName { get; set; }

    /// <summary>
    /// 密码
    /// </summary>
    public string? Password { get; set; }

}

LoginOutPut模型结构如下:

/// <summary>
   /// 登录输入模型
   /// </summary>
   public class LoginOutPut
   {
       /// <summary>
       /// 用户名
       /// </summary>
       public string? UserName { get; set; }

       /// <summary>
       /// 密码
       /// </summary>
       public string? Password { get; set; }

       /// <summary>
       /// Token
       /// </summary>
       public string? Token { get; set; }

       /// <summary>
       /// Token过期时间
       /// </summary>
       public string? ExpiresDate { get; set; }

   }

做完以上操作,用户就可以生成Token,但要把token运用到系统中,还需做以下操作。

创建模块分组

在ModeuleGroupEnum.cs中创建2个枚举,具体如下

/// <summary>
 /// 模块分组
 /// </summary>
 public enum ModeuleGroupEnum
 {
     /// <summary>
     /// 系统菜单
     /// </summary>
     SysMenu = 1,

     /// <summary>
     /// 系统用户
     /// </summary>
     SysUser = 2,

     /// <summary>
     /// 基础
     /// </summary>
     Base = 3,
 }

新增【系统用户】、【基础】2个枚举。

创建新控制器

创建2个控制器:BaseController和SysUserController,结构如下

创建BaseController基础控制器,它存在的作用,就是承担系统中需要重写方法和获取用户基本信息的桥梁。

代码如下:

/// <summary>
/// 系统基础模块
/// </summary>
[ApiController]
[Route("api/[controller]/[action]")]
[ApiExplorerSettings(GroupName = nameof(ModeuleGroupEnum.Base))]
[Authorize]
public class BaseController : ControllerBase
{
    /// <summary>
    /// 获取登陆人员信息
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    public LoginOutPut GetLoginUserMsg()
    {
        StringValues s = new StringValues();
        var auth = Request.Headers.TryGetValue("Authorization", out s);
        if (string.IsNullOrWhiteSpace(s))
            throw new Exception("登录信息失效");
        var token = new JwtSecurityTokenHandler().ReadJwtToken(s.ToString().Replace($"{JwtBearerDefaults.AuthenticationScheme} ", ""));
        LoginOutPut loginResult = new()
        {
            UserName = token.Claims.FirstOrDefault(f => f.Type == "UserName").Value,
            Password = Convert.ToString(token.Claims.FirstOrDefault(f => f.Type == "Password").Value),
        };
        return loginResult;

    }
}

解读下该方法:通过获取Headers中的Token,然后使用jwt反解析token获取在BuildToken方法中记录的用户基本信息。

说明:控制器上方存在[Authorize],只要有控制器继承基础控制【BaseController】,那么该控制器下的所有方法,都需要经过jwt验证。如果某一个接口不需要token验证,就在该接口上方添加 [AllowAnonymous]

创建SysUserController控制器,并继承BaseController控制器,它的作用就是承担系统用户的所有接口,具体代码如下:

/// <summary>
 /// 用户模块
 /// </summary>
 [ApiController]
 [Route("api/[controller]/[action]")]
 [ApiExplorerSettings(GroupName = nameof(ModeuleGroupEnum.SysUser))]
 public class SysUserController : BaseController
 {
     /// <summary>
     /// 获取Token
     /// </summary>
     /// <param name="userName">用户名</param>
     /// <param name="password">密码</param>
     [HttpGet]
     [AllowAnonymous]
     public string GetToken(string userName, string password)
     {
         var loginResult = JwtPlugInUnit.BuildToken(new LoginInput { UserName = userName, Password = password });

         return loginResult.Token ?? string.Empty;
     }
 }

可以看到,该控制器下有2个接口,一个为获取token接口(可同时作为登录接口),一个为获取登录人员信息的接口(继承BaseController下的GetLoginUserMsg()方法)。

做完以上操作,jwt中token验证就完成啦,看一下成果。

不使用token访问接口,不会成功

先获取token

在添加使用token

点击Authorize确定使用

再次访问GetLoginUserMsg()接口,看下效果

文章转载自:陈逸子风

原文链接:https://www.cnblogs.com/cyzf/p/18422784

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构


http://www.kler.cn/a/318770.html

相关文章:

  • Pandas进行MongoDB数据库CRUD
  • 详解python的修饰符
  • 基于Django的个人博客系统的设计与实现
  • shell脚本批量修改文件名之方法(The Method of Batch Modifying File Names in Shell Scripts)
  • C++/stack_queue
  • Solon Cloud Gateway 开发:Route 的过滤器与定制
  • IDEA中Quarkus框架(3.13版本)开发、调试、部署、打包等
  • 通过 OBD Demo 体验 OceanBase 4.3 社区版
  • 关于Hadoop的详细步骤及方案案例
  • python爬虫初体验(三)——将网页数据导出csv和excel文件
  • eCharts扩展图表
  • PDF一键转播客!PDF2Audio让文档“开口说话“
  • 开始学习深度学习-前言
  • 【Docker】Docker快速入门
  • 玩手机数据集 8201张玩手机的照片,有对应的xml和txt文件,可以用于yolo训练
  • 【RabbitMQ】RabbitMQ 的概念以及使用RabbitMQ编写生产者消费者代码
  • 程序包管理器控制台中文乱码
  • 外包功能测试干了4年,技术退步太明显了。。。。。
  • VMWare虚拟机键盘卡顿
  • 主流高级编程语言的推出时间及年份
  • vue脚手架Vue CLI 2.9.6创建工程,并引入elementUI的方法
  • SpringBoot文档管理系统:架构与功能
  • Docker Compose 搭建 Redis 哨兵集群模式搭建详解(1主2从+3哨兵)(包含主从复制的搭建) (保证一遍学会)
  • 【Python大语言模型系列】一文教你使用dify云版本开发一个智能客服机器人(完整教程)
  • 线性判别分析(LDA)中计算两个类的中心点在投影方向w上的投影示例
  • 【质优价廉】GAP9 AI算力处理器赋能智能可听耳机,超低功耗畅享未来音频体验!