CloudBuilder/CloudBuilder.Core/DependencyInjection/Authorization/AuthorizationPack.cs
owenchen 1c0c83af5f ow
2026-05-12 10:09:31 +08:00

136 lines
5.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using CloudBuilder.Core.Application.Builders;
using CloudBuilder.Core.Application.Options;
using CloudBuilder.Core.Application.Packs;
using CloudBuilder.Core.Authorization;
using CloudBuilder.Core.Extensions;
using CloudBuilder.Core.Policy;
using CloudBuilder.Core.Service;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.IdentityModel.Tokens;
using System.Text;
/*
使用JWT
1.认证(AddAuthentication)
1.1开启Bearer认证
1.2注册JwtBearer服务
3.开启中间件(app.UseAuthentication())
4.实现IAuthenticationService接口认证服务
5.实现IAuthorizationPermissionService接口授权服务
2.授权(AddAuthorization)
2.1无状态授权[Authorize]
1.2有状态授权[Authorize["Permission"]] AddAuthorization注册自定义授权
*/
namespace CloudBuilder.Core.DependencyInjection.Authorization
{
[PackLevel(45)]
public class AuthorizationPack : CloudBuilderPack
{
/// <summary>
/// 获取 模块级别
/// </summary>
public override PackLevel Level => PackLevel.Framework;
/// <summary>
/// 获取 模块启动顺序,模块启动的顺序先按级别启动,级别内部再按此顺序启动
/// </summary>
public override int Order => 2;
/// <summary>
/// 将服务添加到依赖注入服务容器中
/// </summary>
/// <param name="services">依赖注入服务容器</param>
/// <returns></returns>
public override IServiceCollection AddServices(IServiceCollection services, CloudBuilderBuilder builder)
{
/*策略授权
1.导入
Microsoft.AspNetCore.Authorization
Microsoft.AspNetCore.Authentication.JwtBearer
2.具体实现逻辑交由外部的PermissionServices:IAuthorizationPermissionService来处理
*/
CloudBuilderOptions section = builder.CloudBuilderOptions;
if (section.Jwt == null) return services;
var signingCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(section.Jwt.Secret)), SecurityAlgorithms.HmacSha256);
// 角色与接口的权限要求参数
var permissionRequirement = new PermissionRequirement();
//初始化认证信息
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
//Token Validation Parameters
x.TokenValidationParameters = new TokenValidationParameters
{
ClockSkew= TimeSpan.Zero,
//通常,验证库(至少是MS之一)可以补偿时钟偏斜。 ClockSkew的默认值为5分钟。
ValidateIssuerSigningKey = true,
//获取或设置要使用的Microsoft.IdentityModel.Tokens.SecurityKey用于签名验证。
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(section.Jwt.Secret)),
//获取或设置一个System.String它表示将使用的有效发行者检查代币的发行者。
ValidIssuer = section.Jwt.Issuer,
//获取或设置一个字符串,该字符串表示将用于检查的有效受众反对令牌的观众。
ValidAudience = section.Jwt.Audience,
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
NameClaimType = ClaimPolicy.CLAINM_USERID,
RoleClaimType = ClaimPolicy.ROLE,
};
});
//启用全局授权(所有的Controller就无需加入Authorize属性如果加入就会重复执行授权)
if (section.EnableGlobalAuthorize)
{
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new AuthorizeFilter());
});
}
//初始化授权信息(使用自定义复杂的授权)
services.AddAuthorization(options =>
{
options.AddPolicy(AuthorizePolicy.PERMISSION, policy => policy.Requirements.Add(permissionRequirement));
});
var baseType = typeof(IAuthorize);
var allAssemblies = CloudBuilderBuilder.GetAssemblies();
var types = allAssemblies
.SelectMany(a => a.DefinedTypes)
.Select(type => type.AsType())
.Where(type => type != baseType && type.HasImplementedRawGeneric(baseType))
.Where(x => x.IsClass).ToList();
foreach (var implementType in types)
{
services.AddScoped(implementType.GetInterfaces().FirstOrDefault(), implementType);
}
services.AddSingleton(new JwtGenerate(section.Jwt));
return services;
}
}
}