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

ASP.NET Core JWT认证与授权

1.JWT结构

JSON Web Token(JWT)是一种用于在网络应用之间安全传输声明的开放标准(RFC 7519)。它通常由三部分组成,以紧凑的字符串形式表示,在身份验证、信息交换等场景中广泛应用。
在这里插入图片描述

2.JWT权限认证

2.1添加认证服务类

在Program类中添加认证服务、Jwt处理类以及JWT配置项。

// 配置 JWT 身份验证
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["JwtOptions:Issuer"],
            ValidAudience = builder.Configuration["JwtOptions:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes(builder.Configuration["JwtOptions:SecurityKey"]))
        };
    });

2.2配置认证中间件

当前端发送请求到后端时,会通过Authentication中间件解析前端发送过来的Bearer,并把解析的数据填充到HttpContext.User中。

app.UseAuthentication();

2.3生成Token

    public string IssueToken()
    {
        var signinCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.SecurityKey)), SecurityAlgorithms.HmacSha256);
        var cls = new List<Claim>()
            {
                new Claim(ClaimTypes.Name, "admin"),
                new Claim("org", "001")
            };

        var tokeOptions = new JwtSecurityToken(
            issuer: jwtOptions.Issuer,
            audience: jwtOptions.Audience,
            claims: cls,
            expires: DateTime.UtcNow.AddSeconds(6400),
            signingCredentials: signinCredentials
        );

        var token = new JwtSecurityTokenHandler().WriteToken(tokeOptions);

        return token;
    }

2.4 appsettings中jwt配置

"JwtOptions": {
  "Issuer": "http://localhost",
  "Audience": "http://localhost",
  "Expires": 3600,
  "SecurityKey": "ThisIsASecretKeyThatIsAtLeast32BytesLongForHS256Algorithm"
}

配置项注入

builder.Services.Configure<JwtOptions>(builder.Configuration.GetSection("JwtOptions"));

2.5 获取认证信息

如果验证成功,就可以从HttContext.User中获取到相关信息。如:HttpContext.User.Identity.IsAuthenticated、HttpContext.User.Identity.Name等。

var user = HttpContext.User;

3.Authentication源代码分析

3.1 JWT认证主要涉及以下类

在这里插入图片描述

3.2 业务流程

在这里插入图片描述

3.3 业务分析

  • 执行AddJwtBearer(options =>{…})方法,往AuthenticationOptions添加AuthenticationSchemeBuilder。
  • 执行AuthenticationMiddleware时,先注入IAuthenticationSchemeProvider对象,IAuthenticationSchemeProvider会通过注入AuthenticationOptions,生成AuthenticationScheme列表。
  • 遍历AuthenticationScheme列表,通过IAuthenticationHandlerProvider对象构建IAuthenicationRequestHandler实例。(IAuthenticationHandlerProvider通过注入IAuthenticationSchemeProvider对象,根据scheme名称找到AuthneticationScheme实例,再找到HandlerType,根据HandlerType生成实例)。
  • 调用JwtBearerHandler解析Bearder,只要有一个Handler处理成功,就结束。

4.授权

4.1授权配置

可以通过配置[Authorize]特性,使得方法的调用必须验证授权。

  • [Authorize]不带任何参数,只验证用户是否登录
[Authorize]
public IActionResult Privacy()
  • [Authorize(Roles =“admin”)]配置角色,验证用户是否属于要求的角色。角色是或者的关系,只需要满足一个就验证通过。
[Authorize(Roles ="admin,operate")]
public IActionResult Privacy()
  • 自定义配置策略
[Authorize("MinimumAgePolicy")]
public string Test()
 // 添加验证策略,策略是且的关系,必须全部满足才验证通过
 builder.Services.AddAuthorization(options =>
 {
     options.AddPolicy("MinimumAgePolicy", policy => policy.Requirements.Add(new MinimumAgeRequirement(18)));
 });
 
  public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
 {
     protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MinimumAgeRequirement requirement)
     {
         if (context.User.HasClaim(c => c.Type == ClaimTypes.DateOfBirth))
         {
             var dateOfBirth = Convert.ToDateTime(context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth).Value);
             var age = DateTime.Today.Year - dateOfBirth.Year;
             if (dateOfBirth > DateTime.Today.AddYears(-age))
             {
                 age--;
             }

             if (age >= requirement.MinimumAge)
             {
                 context.Succeed(requirement);
             }
         }

         return Task.CompletedTask;
     }


 }

 public class MinimumAgeRequirement : IAuthorizationRequirement
 {
     public int MinimumAge { get; set; }

     public MinimumAgeRequirement(int minimumAge)
     {
         MinimumAge = minimumAge;
     }
 }

5. Authorization源码分析

5.1类图

在这里插入图片描述

在这里插入图片描述

5.2代码分析

以下代码在AuthorizationOptions类中添加AuthorizationPolicy,每个AuthorizationPolicy包含多个IAuthorizationRequirement。每个IAuthorizationRequirement代表一个验证项。

 builder.Services.AddAuthorization(options =>
 {
     options.AddPolicy("MinimumAgePolicy", policy => policy.Requirements.Add(new MinimumAgeRequirement(18)));
 });
  • 注入中间件AuthorizationMiddleware,当请求到达时,中间件会获取当前EndPoint信息(IAuthorizeData),如根据[Authorize(“MinimumAgePolicy”)]获取AuthorizationPolicy。

  • 获取AuthorizationPolicy会判断是否有配置Roles,如果有配置,则会在Policy对象中添加RolesAuthorizationRequirement对象。(policy = await AuthorizationPolicy.CombineAsync(_policyProvider, authorizeData, policies)😉

  • 调用DefaultAuthorizationService,验证AuthorizationPolicy。

  • DefaultAuthorizationService会获取所有注入的IAuthorizationHandler,遍历所有的Handler,根据Handler所要求的Requirement,从AuthorizationPolicy中获取实例传入Handler中。Handler验证成功,会删除对应的Requirement。所有Requirement都删除了才算验证成功。

app.UseAuthorization();

针对系统自带Requirement,比如配置Roles添加RolesAuthorizationRequirement对象。在AddAuthorization->AddAuthorizationCore中会注入PassThroughAuthorizationHandler。该Handler会遍历系统自带的Requirement(系统自带的Requirement会继承AuthorizationHandler并实现IAuthorizationRequirement),直接调用HandleAsync方法。

services.TryAddEnumerable(ServiceDescriptor.Transient<IAuthorizationHandler, PassThroughAuthorizationHandler>());

相关文章:

  • rust学习笔记12-hashmap与1. 两数之和
  • 【C语言】值传递与指针传递,以及 `.` 和 `->` 操作详解
  • 设备预测性维护的6大应用场景
  • vue 安装依赖npm install过程中报错npm ERR! cb() never called!
  • 【电控笔记z69】电机选型-机械特性
  • deepseek本地集群部署调研
  • GCC RISCV 后端 -- cc1 入口
  • 批量插入对比-mysql-oracle-sqlserver
  • Three.js 新前端学习
  • tauri-plugin-shell插件将_blank的a标签用浏览器打开了,,,解决办法
  • android为第三方提供部分系统接口
  • Linux 系统不同分类的操作命令区别
  • Windows系统编程(八)线程同步
  • 【gRPC】Java高性能远程调用之gRPC详解
  • 大语言模型中温度参数(Temperature)的核心原理
  • 大学至今的反思与总结
  • python-leetcode-零钱兑换 II
  • EasyRTC嵌入式视频通话SDK的跨平台适配,构建web浏览器、Linux、ARM、安卓等终端的低延迟音视频通信
  • 内核编程七:Linux 内核日志的级别
  • DeepSeek大模型深度解析:架构、技术与应用全景
  • 李公明 | 一周画记:德里达哲学还是接地气的
  • 国家统计局:1-4月份,全国固定资产投资同比增长4.0%
  • 从《缶翁的世界》开始,看吴昌硕等湖州籍书画家对海派的影响
  • 视频丨为救心梗同学缺席职教高考的小伙姜昭鹏完成补考
  • AI赋能科学红毯,机器人与科学家在虚实之间叩问“科学精神”
  • 浙江省委金融办原副主任潘广恩被“双开”