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
{
///
/// 获取 模块级别
///
public override PackLevel Level => PackLevel.Framework;
///
/// 获取 模块启动顺序,模块启动的顺序先按级别启动,级别内部再按此顺序启动
///
public override int Order => 2;
///
/// 将服务添加到依赖注入服务容器中
///
/// 依赖注入服务容器
///
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(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;
}
}
}