Identity – Authorize Custom Authorization Policy Providers

前言

上一篇讲完了基本使用 Policy-Based. 这一篇另外说一说怎么动态调用它.

参考: Custom Authorization Policy Providers using IAuthorizationPolicyProvider in ASP.NET Core

需求和实现思路

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AtLeast21", policy =>
        policy.Requirements.Add(new MinimumAgeRequirement(21)));
});

比如说 21 这个变量我想通过 SQL 输出可以吗? 

Policy 和 Requirement 的关系可以都保存在 SQL 吗? 然后要改就改.

依据上面的代码来分析出实现手法的话, 大概可以这样做, 在 builder.Services 的期间, 发请求到 SQL, 

然后通过反射调用执行完上面的所有代码. 这样应该就 ok 了. 但即便是这样, 由于是在 StartUp setup 1 time, 除非重启, 不然这些配置是能即刻被修改的.

那 ASP.NET Core 是否提供了更便利的接口呢?

有的, 那就是 Authorization Policy Providers

我们实现一个 Policy Provider, 它的职责是, 当有人要求一个 Policy 时 (by name), Provider 就提供一个 Policy 实例.

这个 Policy 实例, 要通过 SQL 还是任何复杂逻辑都可以. 一个工厂模式就对了.

具体实现

Create PolicyProvider

public class MyPolicyProvider : DefaultAuthorizationPolicyProvider
{
    public MyPolicyProvider(IOptions<AuthorizationOptions> options) : base(options)
    {
    }

    public override Task<AuthorizationPolicy?> GetPolicyAsync(string policyName)
    {
        return base.GetPolicyAsync(policyName);
    }
}

底层接口是

GetPolicyAsync 就是依据 PolicyName 获取 Policy

GetDefaultPolicyAsync 则是 [Authorize] 这种没有声明 Policy 的

GetFallbackPolicyAsync 和 GetDefaultPolicyAsync 一样, 都是没有声明 Policy 的 autho, 只是它用于 Authorization Middleware

一般上都是继承 DefaultAuthorizationPolicyProvider 然后 override GetPolicyAsync 就够用了

Register Provider

必须是 Singleton 哦

builder.Services.AddSingleton<IAuthorizationPolicyProvider, MyPolicyProvider>();

由于是 Singleton 可能会无法 inject scope service, 解决方案是 Implementing a custom IAuthorizationPolicyProvider with database access

然后, 每一次只要有需要 Policy, PolicyProvider.GetPolicyAsync 就会被调用.

常见用法

自定义一个 AuthorizeAttribute, 然后动态声明 PolicyName

在通过 custom policy provider, 把这个名字拆开取出 age, pass to AgeRequirement. 这样就形成了一个 dynamic age requirement 验证.

原文地址:https://www.cnblogs.com/keatkeat/p/15634801.html