|
|
@ -1,99 +1,95 @@ |
|
|
|
using Tiobon.Core.AuthHelper; |
|
|
|
using System.Security.Claims; |
|
|
|
using Tiobon.Core.Common; |
|
|
|
using System.Text; |
|
|
|
using Tiobon.Core.Common.AppConfig; |
|
|
|
|
|
|
|
using Microsoft.AspNetCore.Authorization; |
|
|
|
using Microsoft.AspNetCore.Authorization; |
|
|
|
using Microsoft.AspNetCore.Http; |
|
|
|
using Microsoft.AspNetCore.Http; |
|
|
|
using Microsoft.Extensions.DependencyInjection; |
|
|
|
using Microsoft.Extensions.DependencyInjection; |
|
|
|
using Microsoft.IdentityModel.Tokens; |
|
|
|
using Microsoft.IdentityModel.Tokens; |
|
|
|
using System; |
|
|
|
using Tiobon.Core.AuthHelper; |
|
|
|
using System.Collections.Generic; |
|
|
|
using Tiobon.Core.Common; |
|
|
|
using System.Security.Claims; |
|
|
|
using Tiobon.Core.Common.AppConfig; |
|
|
|
using System.Text; |
|
|
|
|
|
|
|
using System.Security; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace Tiobon.Core.Extensions |
|
|
|
namespace Tiobon.Core.Extensions; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
|
|
|
/// 系统 授权服务 配置 |
|
|
|
|
|
|
|
/// </summary> |
|
|
|
|
|
|
|
public static class AuthorizationSetup |
|
|
|
{ |
|
|
|
{ |
|
|
|
/// <summary> |
|
|
|
public static void AddAuthorizationSetup(this IServiceCollection services) |
|
|
|
/// 系统 授权服务 配置 |
|
|
|
|
|
|
|
/// </summary> |
|
|
|
|
|
|
|
public static class AuthorizationSetup |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
public static void AddAuthorizationSetup(this IServiceCollection services) |
|
|
|
if (services == null) throw new ArgumentNullException(nameof(services)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 以下四种常见的授权方式。 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 1、这个很简单,其他什么都不用做, 只需要在API层的controller上边,增加特性即可 |
|
|
|
|
|
|
|
// [Authorize(Roles = "Admin,System")] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 2、这个和上边的异曲同工,好处就是不用在controller中,写多个 roles 。 |
|
|
|
|
|
|
|
// 然后这么写 [Authorize(Policy = "Admin")] |
|
|
|
|
|
|
|
services.AddAuthorization(options => |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
options.AddPolicy("Client", policy => policy.RequireRole("Client").Build()); |
|
|
|
|
|
|
|
options.AddPolicy("Admin", policy => policy.RequireRole("Admin").Build()); |
|
|
|
|
|
|
|
options.AddPolicy("SystemOrAdmin", policy => policy.RequireRole("Admin", "System")); |
|
|
|
|
|
|
|
options.AddPolicy("A_S_O", policy => policy.RequireRole("Admin", "System", "Others")); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region 参数 |
|
|
|
|
|
|
|
//读取配置文件 |
|
|
|
|
|
|
|
var symmetricKeyAsBase64 = AppSecretConfig.Audience_Secret_String; |
|
|
|
|
|
|
|
var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64); |
|
|
|
|
|
|
|
var signingKey = new SymmetricSecurityKey(keyByteArray); |
|
|
|
|
|
|
|
var Issuer = AppSettings.app(new string[] { "Audience", "Issuer" }); |
|
|
|
|
|
|
|
var Audience = AppSettings.app(new string[] { "Audience", "Audience" }); |
|
|
|
|
|
|
|
var ExpirationHourString = AppSettings.app(new string[] { "Audience", "ExpirationHour" }); |
|
|
|
|
|
|
|
var ExpirationHour = string.IsNullOrWhiteSpace(ExpirationHourString) ? 4 : Convert.ToInt32(ExpirationHourString) + 1; |
|
|
|
|
|
|
|
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果要数据库动态绑定,这里先留个空,后边处理器里动态赋值 |
|
|
|
|
|
|
|
var permission = new List<PermissionItem>(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 角色与接口的权限要求参数 |
|
|
|
|
|
|
|
var permissionRequirement = new PermissionRequirement( |
|
|
|
|
|
|
|
"/api/denied",// 拒绝授权的跳转地址(目前无用) |
|
|
|
|
|
|
|
permission, |
|
|
|
|
|
|
|
ClaimTypes.Role,//基于角色的授权 |
|
|
|
|
|
|
|
Issuer,//发行人 |
|
|
|
|
|
|
|
Audience,//听众 |
|
|
|
|
|
|
|
signingCredentials,//签名凭据 |
|
|
|
|
|
|
|
expiration: TimeSpan.FromSeconds(60 * 60 * ExpirationHour)//接口的过期时间 |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
#endregion |
|
|
|
|
|
|
|
// 3、自定义复杂的策略授权 |
|
|
|
|
|
|
|
services.AddAuthorization(options => |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (services == null) throw new ArgumentNullException(nameof(services)); |
|
|
|
options.AddPolicy(Permissions.Name, |
|
|
|
|
|
|
|
policy => policy.Requirements.Add(permissionRequirement)); |
|
|
|
// 以下四种常见的授权方式。 |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// 1、这个很简单,其他什么都不用做, 只需要在API层的controller上边,增加特性即可 |
|
|
|
|
|
|
|
// [Authorize(Roles = "Admin,System")] |
|
|
|
// 4、基于Scope策略授权 |
|
|
|
|
|
|
|
//services.AddAuthorization(options => |
|
|
|
|
|
|
|
//{ |
|
|
|
// 2、这个和上边的异曲同工,好处就是不用在controller中,写多个 roles 。 |
|
|
|
// options.AddPolicy("Scope_TiobonModule_Policy", builder => |
|
|
|
// 然后这么写 [Authorize(Policy = "Admin")] |
|
|
|
// { |
|
|
|
services.AddAuthorization(options => |
|
|
|
// //客户端Scope中包含Tiobon.core.api.TiobonModule才能访问 |
|
|
|
{ |
|
|
|
// // 同时引用nuget包:IdentityServer4.AccessTokenValidation |
|
|
|
options.AddPolicy("Client", policy => policy.RequireRole("Client").Build()); |
|
|
|
// builder.RequireScope("Tiobon.core.api.TiobonModule"); |
|
|
|
options.AddPolicy("Admin", policy => policy.RequireRole("Admin").Build()); |
|
|
|
// }); |
|
|
|
options.AddPolicy("SystemOrAdmin", policy => policy.RequireRole("Admin", "System")); |
|
|
|
|
|
|
|
options.AddPolicy("A_S_O", policy => policy.RequireRole("Admin", "System", "Others")); |
|
|
|
// // 其他 Scope 策略 |
|
|
|
}); |
|
|
|
// // ... |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 这里冗余写了一次,因为很多人看不到 |
|
|
|
#region 参数 |
|
|
|
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); |
|
|
|
//读取配置文件 |
|
|
|
// 注入权限处理器 |
|
|
|
var symmetricKeyAsBase64 = AppSecretConfig.Audience_Secret_String; |
|
|
|
services.AddScoped<IAuthorizationHandler, PermissionHandler>(); |
|
|
|
var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64); |
|
|
|
services.AddSingleton(permissionRequirement); |
|
|
|
var signingKey = new SymmetricSecurityKey(keyByteArray); |
|
|
|
|
|
|
|
var Issuer = AppSettings.app(new string[] { "Audience", "Issuer" }); |
|
|
|
|
|
|
|
var Audience = AppSettings.app(new string[] { "Audience", "Audience" }); |
|
|
|
|
|
|
|
var ExpirationHourString = AppSettings.app(new string[] { "Audience", "ExpirationHour" }); |
|
|
|
|
|
|
|
var ExpirationHour = string.IsNullOrWhiteSpace(ExpirationHourString) ? 4 : Convert.ToInt32(ExpirationHourString); |
|
|
|
|
|
|
|
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果要数据库动态绑定,这里先留个空,后边处理器里动态赋值 |
|
|
|
|
|
|
|
var permission = new List<PermissionItem>(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 角色与接口的权限要求参数 |
|
|
|
|
|
|
|
var permissionRequirement = new PermissionRequirement( |
|
|
|
|
|
|
|
"/api/denied",// 拒绝授权的跳转地址(目前无用) |
|
|
|
|
|
|
|
permission, |
|
|
|
|
|
|
|
ClaimTypes.Role,//基于角色的授权 |
|
|
|
|
|
|
|
Issuer,//发行人 |
|
|
|
|
|
|
|
Audience,//听众 |
|
|
|
|
|
|
|
signingCredentials,//签名凭据 |
|
|
|
|
|
|
|
expiration: TimeSpan.FromSeconds(240 * 60 * ExpirationHour)//接口的过期时间 |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
#endregion |
|
|
|
|
|
|
|
// 3、自定义复杂的策略授权 |
|
|
|
|
|
|
|
services.AddAuthorization(options => |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
options.AddPolicy(Permissions.Name, |
|
|
|
|
|
|
|
policy => policy.Requirements.Add(permissionRequirement)); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 4、基于Scope策略授权 |
|
|
|
|
|
|
|
//services.AddAuthorization(options => |
|
|
|
|
|
|
|
//{ |
|
|
|
|
|
|
|
// options.AddPolicy("Scope_TiobonModule_Policy", builder => |
|
|
|
|
|
|
|
// { |
|
|
|
|
|
|
|
// //客户端Scope中包含Tiobon.core.api.TiobonModule才能访问 |
|
|
|
|
|
|
|
// // 同时引用nuget包:IdentityServer4.AccessTokenValidation |
|
|
|
|
|
|
|
// builder.RequireScope("Tiobon.core.api.TiobonModule"); |
|
|
|
|
|
|
|
// }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // 其他 Scope 策略 |
|
|
|
|
|
|
|
// // ... |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 这里冗余写了一次,因为很多人看不到 |
|
|
|
|
|
|
|
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); |
|
|
|
|
|
|
|
// 注入权限处理器 |
|
|
|
|
|
|
|
services.AddScoped<IAuthorizationHandler, PermissionHandler>(); |
|
|
|
|
|
|
|
services.AddSingleton(permissionRequirement); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|