ASP.NET Core JWT认证与授权

发布于:2025-03-05 ⋅ 阅读:(13) ⋅ 点赞:(0)

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>());

网站公告

今日签到

点亮在社区的每一天
去签到