ASP.NET Core运行时动态增减AuthorizationPolicy中的认证方案
动态管理ASP.NET Core 8认证方案与授权策略的解决方案
要实现运行时开启/关闭认证方案并同步更新授权策略,核心是自定义动态授权策略提供者,替代默认的固定策略逻辑,让授权策略能实时感知当前启用的认证方案。以下是具体实现步骤:
1. 自定义动态授权策略提供者
实现IAuthorizationPolicyProvider,结合IAuthenticationSchemeProvider获取当前有效认证方案,动态构建授权策略,并加入缓存优化性能:
public class DynamicAuthorizationPolicyProvider : IAuthorizationPolicyProvider { private readonly DefaultAuthorizationPolicyProvider _defaultProvider; private readonly IAuthenticationSchemeProvider _schemeProvider; private AuthorizationPolicy? _cachedDefaultPolicy; private readonly object _cacheLock = new(); private readonly IConfiguration _configuration; public DynamicAuthorizationPolicyProvider(IOptions<AuthorizationOptions> options, IAuthenticationSchemeProvider schemeProvider, IConfiguration configuration) { _defaultProvider = new DefaultAuthorizationPolicyProvider(options); _schemeProvider = schemeProvider; _configuration = configuration; } public async Task<AuthorizationPolicy?> GetPolicyAsync(string policyName) { // 非默认策略交给默认提供者处理 if (!string.Equals(policyName, AuthorizationPolicy.DefaultPolicyName, StringComparison.OrdinalIgnoreCase)) { return await _defaultProvider.GetPolicyAsync(policyName); } // 优先用缓存的策略,避免重复构建 lock (_cacheLock) { if (_cachedDefaultPolicy != null) return _cachedDefaultPolicy; } // 获取所有已注册且启用的认证方案 var enabledSchemes = (await _schemeProvider.GetAllSchemesAsync()) .Where(s => IsSchemeEnabled(s.Name)) .Select(s => s.Name) .ToList(); // 动态构建默认授权策略 var policy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .AddAuthenticationSchemes(enabledSchemes.ToArray()) .Build(); lock (_cacheLock) { _cachedDefaultPolicy = policy; } return policy; } public Task<AuthorizationPolicy> GetDefaultPolicyAsync() { return GetPolicyAsync(AuthorizationPolicy.DefaultPolicyName) ?? _defaultProvider.GetDefaultPolicyAsync(); } public Task<AuthorizationPolicy?> GetFallbackPolicyAsync() { return _defaultProvider.GetFallbackPolicyAsync(); } // 刷新缓存:当认证方案启用/禁用时调用 public void RefreshPolicyCache() { lock (_cacheLock) { _cachedDefaultPolicy = null; } } // 自定义判断方案是否启用的逻辑(可从配置、数据库读取) private bool IsSchemeEnabled(string schemeName) { // 示例:从配置读取启用状态,可替换为数据库查询等逻辑 return schemeName switch { JwtBearerDefaults.AuthenticationScheme => true, // JWT默认始终启用 Contants.MyCustomAuthScheme => _configuration.GetValue<bool>("Auth:CustomSchemeEnabled"), _ => true // 其他方案默认启用,可按需调整 }; } }
2. 注册自定义提供者与认证方案
在ConfigureServices中注册自定义授权策略提供者,同时配置所有可能用到的认证方案:
var builder = WebApplication.CreateBuilder(args); // 注册自定义授权策略提供者 builder.Services.AddSingleton<IAuthorizationPolicyProvider, DynamicAuthorizationPolicyProvider>(); // 配置所有支持的认证方案 builder.Services.AddAuthentication() .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => { // 你的JWT配置逻辑,比如Authority、Audience等 }) .AddScheme<MyCustomAuthOptions, MyCustomAuthHandler>(Contants.MyCustomAuthScheme, options => { // 自定义认证方案的配置 }); // 其他服务注册... var app = builder.Build(); // 中间件配置... app.UseAuthentication(); app.UseAuthorization();
3. 运行时启用/禁用认证方案
在控制器中实现动态操作逻辑,修改认证方案注册状态、更新启用配置,并刷新授权策略缓存:
[ApiController] [Route("api/auth-schemes")] public class AuthSchemeController : ControllerBase { private readonly IAuthenticationSchemeProvider _schemeProvider; private readonly DynamicAuthorizationPolicyProvider _policyProvider; private readonly IConfiguration _configuration; public AuthSchemeController(IAuthenticationSchemeProvider schemeProvider, DynamicAuthorizationPolicyProvider policyProvider, IConfiguration configuration) { _schemeProvider = schemeProvider; _policyProvider = policyProvider; _configuration = configuration; } [HttpPost("enable/{schemeName}")] public async Task<IActionResult> EnableScheme(string schemeName) { // 向SchemeProvider添加方案(如果未注册) var existingScheme = await _schemeProvider.GetSchemeAsync(schemeName); if (existingScheme == null) { var scheme = schemeName switch { Contants.MyCustomAuthScheme => new AuthenticationScheme(schemeName, "自定义认证", typeof(MyCustomAuthHandler)), // 其他方案的注册逻辑... _ => throw new ArgumentException("不支持的认证方案") }; await _schemeProvider.AddSchemeAsync(scheme); } // 更新启用状态配置 _configuration[$"Auth:{schemeName}Enabled"] = "true"; // 刷新授权策略缓存 _policyProvider.RefreshPolicyCache(); return Ok($"已启用认证方案:{schemeName}"); } [HttpPost("disable/{schemeName}")] public async Task<IActionResult> DisableScheme(string schemeName) { // 从SchemeProvider移除方案 await _schemeProvider.RemoveSchemeAsync(schemeName); // 更新启用状态配置 _configuration[$"Auth:{schemeName}Enabled"] = "false"; // 刷新授权策略缓存 _policyProvider.RefreshPolicyCache(); return Ok($"已禁用认证方案:{schemeName}"); } }
关键说明
- 自定义授权策略提供者会在每次请求默认策略时,自动读取当前启用的认证方案,无需手动修改原有固定策略。
- 缓存机制避免了频繁查询认证方案的性能损耗,仅在方案状态变化时清空缓存。
- 启用/禁用逻辑需同时维护
IAuthenticationSchemeProvider的注册状态和启用配置,确保两端同步。
内容的提问来源于stack exchange,提问作者Stephan Steiner
相关产品推荐
相关产品推荐

