Skip to content

Commit

Permalink
feat(src/plugincore.aspnetcore): 认证与授权: 优化,分离, PluginCoreStartupExten…
Browse files Browse the repository at this point in the history
…sions 优化
  • Loading branch information
yiyungent committed Feb 14, 2024
1 parent 596a481 commit ebab6d8
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 48 deletions.
8 changes: 4 additions & 4 deletions src/PluginCore.AspNetCore/Authorization/AccountManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@



using System;
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Http;
Expand Down Expand Up @@ -37,7 +37,7 @@ public AccountManager(IHttpContextAccessor httpContextAccessor)
_httpContextAccessor = httpContextAccessor;
}

public Config.PluginCoreConfig.AdminModel Admin
public static Config.PluginCoreConfig.AdminModel Admin
{
get
{
Expand Down Expand Up @@ -98,12 +98,12 @@ public string CurrentToken()
return token;
}

public string CreateToken()
public static string CreateToken()
{
return CreateToken(Admin.UserName, Admin.Password);
}

public string CreateToken(string userName, string password)
public static string CreateToken(string userName, string password)
{
string token = $"UserName={userName}&Password={password}";
token = Md5Helper.MD5Encrypt32(token);
Expand Down
2 changes: 1 addition & 1 deletion src/PluginCore.AspNetCore/Controllers/UserController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public async Task<ActionResult<BaseResponseModel>> Login([FromBody] LoginRequest

try
{
string token = this._accountManager.CreateToken(requestModel.UserName, requestModel.Password);
string token = AccountManager.CreateToken(requestModel.UserName, requestModel.Password);
bool isAdmin = this._accountManager.IsAdminToken(token);
if (!isAdmin)
{
Expand Down
151 changes: 110 additions & 41 deletions src/PluginCore.AspNetCore/Extensions/PluginCoreStartupExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,69 @@ public static class PluginCoreStartupExtensions
/// </summary>
/// <param name="services"></param>
public static void AddPluginCore(this IServiceCollection services)
{
services.AddPluginCoreServices();

services.AddPluginCorePlugins();

#region PluginCore Admin 权限
// 1. 先 Authentication (我是谁) 2. 再 Authorization (我能做什么)

// Authentication
services.AddPluginCoreAuthentication();

// Authorization
services.AddPluginCoreAuthorization();
#endregion

services.AddPluginCoreStartupPlugin();

services.AddPluginCoreLog();

// AddBackgroundServices
services.AddBackgroundServices();

// 一定要在最后
_services = services;
}

public static IApplicationBuilder UsePluginCore(this IApplicationBuilder app)
{
// 一定在 PluginCore 添加的中间件中 第一个
app.UseMiddleware<PluginHttpStartFilterMiddleware>();

app.UsePluginCoreLanguageMiddleware();

app.UsePluginCoreAdminUI();

app.UsePluginCoreStaticFiles();

// 发现 UseAuthentication 认证中间件重复添加, 也只会执行一次 认证
// 但 UseAuthorization 重复添加2次, 则会执行 2次 授权
app.UseAuthentication();
app.UseAuthorization();

#region Plugin Middleware
// Plugin Middleware
//app.UseMiddleware<PluginContentFilterMiddleware>();


// 一定在 PluginCore 添加的中间件中 最后一个
app.UseMiddleware<PluginHttpEndFilterMiddleware>();
#endregion

app.UsePluginCoreAppStart();

app.UsePluginCoreStartupPlugin();

// Log
app.UsePluginCoreLog();

return app;
}


public static void AddPluginCoreServices(this IServiceCollection services)
{
#region 注册服务

Expand Down Expand Up @@ -97,11 +160,12 @@ public static void AddPluginCore(this IServiceCollection services)

#endregion



// ************************* 注意: IServiceCollection 是服务列表, 但由 IServiceProvider 来负责解析, AClass 单例 仅在 AServiceProvider 范围内
_serviceProvider = services.BuildServiceProvider();
}

public static void AddPluginCorePlugins(this IServiceCollection services)
{
#region ASP.NET Core
//IPluginManager pluginManager = services.BuildServiceProvider().GetService<IPluginManager>();
IPluginManager pluginManager = _serviceProvider.GetService<IPluginManager>();
Expand All @@ -126,7 +190,6 @@ public static void AddPluginCore(this IServiceCollection services)
#endregion



// 将本 Assembly 内的 Controller 添加
var ass = Assembly.GetExecutingAssembly();
//IPluginControllerManager pluginControllerManager = services.BuildServiceProvider().GetService<IPluginControllerManager>();
Expand All @@ -137,10 +200,10 @@ public static void AddPluginCore(this IServiceCollection services)
// IWebHostEnvironment
_webHostEnvironment = services.BuildServiceProvider().GetService<IWebHostEnvironment>();
#endregion
}

#region PluginCore Admin 权限
// 1. 先 Authentication (我是谁) 2. 再 Authorization (我能做什么)

public static void AddPluginCoreAuthentication(this IServiceCollection services)
{
// fixed: https://github.com/yiyungent/PluginCore/issues/4
// System.InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions).
#region 添加认证 Authentication
Expand All @@ -159,9 +222,13 @@ public static void AddPluginCore(this IServiceCollection services)
displayName: Constants.AspNetCoreAuthenticationScheme,
options => { });
#endregion
}

public static void AddPluginCoreAuthorization(this IServiceCollection services)
{
#region 添加授权策略-所有标记 [PluginCoreAdminAuthorize] 都需要权限检查
services.AddSingleton<IAuthorizationHandler, PluginCoreAdminAuthorizationHandler>();
// Only Once, Not recommend
//services.AddSingleton<IAuthorizationHandler, PluginCoreAdminAuthorizationHandler>();

services.AddAuthorization(options =>
{
Expand All @@ -170,21 +237,34 @@ public static void AddPluginCore(this IServiceCollection services)
{
// 无法满足 下方任何一项:HTTP 403 错误
// 3.需要 检查是否拥有当前请求资源的权限
policy.Requirements.Add(new PluginCoreAdminRequirement());
//policy.Requirements.Add(new PluginCoreAdminRequirement());
policy.AuthenticationSchemes = new string[] {
Constants.AspNetCoreAuthenticationScheme
};
policy.RequireAuthenticatedUser();
policy.RequireClaim(claimType: Constants.AspNetCoreAuthenticationClaimType);
// 必须重启才能使得更改密码生效
string token = AccountManager.CreateToken();
policy.RequireClaim(claimType: Constants.AspNetCoreAuthenticationClaimType, allowedValues: new string[] {
token
});
//policy.RequireAssertion(context =>
//{
// return true;
//});
});
});
#endregion


// AccountManager
services.AddTransient<AccountManager>();
// HttpContext.Current
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
//services.AddHttpContextAccessor();
#endregion
}

public static void AddPluginCoreStartupPlugin(this IServiceCollection services)
{
//IPluginFinder pluginFinder = services.BuildServiceProvider().GetService<IPluginFinder>();
IPluginFinder pluginFinder = _serviceProvider.GetService<IPluginFinder>();

Expand All @@ -200,30 +280,20 @@ public static void AddPluginCore(this IServiceCollection services)
}

#endregion
}

public static void AddPluginCoreLog(this IServiceCollection services)
{
#region Logger

IServiceScopeFactory serviceScopeFactory = _serviceProvider.GetService<IServiceScopeFactory>();
Utils.LogUtil.Initialize(serviceScopeFactory);

#endregion

// AddBackgroundServices
services.AddBackgroundServices();

// 一定要在最后
_services = services;
}

public static IApplicationBuilder UsePluginCore(this IApplicationBuilder app)
public static IApplicationBuilder UsePluginCoreStaticFiles(this IApplicationBuilder app)
{
// 一定在 PluginCore 添加的中间件中 第一个
app.UseMiddleware<PluginHttpStartFilterMiddleware>();

app.UseLanguageMiddleware();

app.UsePluginCoreAdminUI();

// 由于没办法在运行时, 动态 UseStaticFiles(), 因此不再为每一个插件都 UseStaticFiles(),
// 而是统一在一个文件夹下, 插件启用时, 将插件的wwwroot复制到 Plugins_wwwroot/{PluginId}, 禁用时, 再删除
string pluginwwwrootDir = PluginPathProvider.PluginsWwwRootDir();
Expand All @@ -234,22 +304,11 @@ public static IApplicationBuilder UsePluginCore(this IApplicationBuilder app)
RequestPath = "/Plugins"
});

return app;
}

// 发现 UseAuthentication 认证中间件重复添加, 也只会执行一次 认证
// 但 UseAuthorization 重复添加2次, 则会执行 2次 授权
app.UseAuthentication();
app.UseAuthorization();

#region Plugin Middleware
// Plugin Middleware
//app.UseMiddleware<PluginContentFilterMiddleware>();


// 一定在 PluginCore 添加的中间件中 最后一个
app.UseMiddleware<PluginHttpEndFilterMiddleware>();
#endregion


public static IApplicationBuilder UsePluginCoreAppStart(this IApplicationBuilder app)
{
//IPluginFinder pluginFinder = _services.BuildServiceProvider().GetService<IPluginFinder>();
IPluginFinder pluginFinder = _serviceProvider.GetService<IPluginFinder>();

Expand All @@ -274,6 +333,14 @@ public static IApplicationBuilder UsePluginCore(this IApplicationBuilder app)

#endregion

return app;
}

public static IApplicationBuilder UsePluginCoreStartupPlugin(this IApplicationBuilder app)
{
//IPluginFinder pluginFinder = _services.BuildServiceProvider().GetService<IPluginFinder>();
IPluginFinder pluginFinder = _serviceProvider.GetService<IPluginFinder>();

#region IStartupPlugin

var startupPlugins = pluginFinder.EnablePlugins<IStartupPlugin>()?.OrderBy(m => m.ConfigureOrder)?.ToList();
Expand All @@ -291,7 +358,11 @@ public static IApplicationBuilder UsePluginCore(this IApplicationBuilder app)

app.UseMiddleware<PluginStartupXMiddleware>();

return app;
}

public static IApplicationBuilder UsePluginCoreLog(this IApplicationBuilder app)
{
#region 启动 Log
Config.PluginCoreConfig pluginCoreConfig = Config.PluginCoreConfigFactory.Create();

Expand All @@ -303,8 +374,6 @@ public static IApplicationBuilder UsePluginCore(this IApplicationBuilder app)

return app;
}


}
}

Expand Down
4 changes: 2 additions & 2 deletions src/PluginCore.AspNetCore/Middlewares/LanguageMiddleware.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===================================================
//===================================================
// License: GNU LGPLv3
// Contributors: yiyungent@gmail.com
// Project: https://yiyungent.github.io/PluginCore
Expand Down Expand Up @@ -39,7 +39,7 @@ public async Task Invoke(HttpContext httpContext)

public static class LanguageMiddlewareExtensions
{
public static IApplicationBuilder UseLanguageMiddleware(this IApplicationBuilder builder)
public static IApplicationBuilder UsePluginCoreLanguageMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<LanguageMiddleware>();
}
Expand Down

0 comments on commit ebab6d8

Please sign in to comment.