是否可以内联运行策略的所有处理程序,而不是使用属性?

Possible to run all handlers for a policy in-line instead of with an attribute?

提问人:user3715648 提问时间:2/13/2020 更新时间:2/26/2020 访问量:229

问:

在我的大多数 API 上,我只是像这样进行授权:

[Authorize(Policy = "Foo")]
public MyApi()

我从NuGet获取此策略,但无法修改它。

对于我的某些 API,我并不总是希望有这个策略。这需要在运行时根据一些配置来弄清楚。我想要某种方式来内联运行它,并确保所有设置的处理程序都运行。

经过大量搜索,我发现我创建了一个 ,并用它来调用 .这似乎是我想要的,但我现在遇到的问题是所有处理程序都依赖 an 作为上下文中的资源。当通过属性完成授权时,这似乎会自动发生,而不是通过对 AuthorizeAsync 的调用。在这种情况下,它需要手动传入。我的代码现在看起来像这样:IAuthorizationServiceAuthorizeAsyncAuthorizationFilterContext

public MyApi()
{
    var allowed = await _authorizationService.AuthorizeAsync(User, null, "Foo").ConfigureAwait(false);
}

这似乎正确地遍历了我的所有处理程序,但由于缺少 .AuthorizationFilterContext

1) 这是正确的方法,还是有其他方法可以内联完成?我猜可能有某种方法可以创建我自己的策略来包装这个策略,我可以检查那里的配置,但如果有一个简单的内联方法,我更喜欢它。

2)如果这种方式有效,有没有一种好的方法可以得到?我尝试过手动创建它,但恐怕如果不从上下文中传入更多数据,这实际上并不正确,但我找不到任何好的例子/文档:AuthorizationFilterContext

new AuthorizationFilterContext(new ActionContext(HttpContext, HttpContext.GetRouteData(), new ActionDescriptor()), new IFilterMetadata[] { });

C# 授权 Net-2.0

评论

0赞 curiousBoy 2/26/2020
这是一种非常糟糕的方法。首先,任何调用现在都可以命中您的 api 方法,即使它们没有访问权限,因为您稍后会进行访问检查。为自己创建一个自定义属性,您可以轻松检查要检查的任何策略(单个或多个)是否归用户所有。也很高兴阅读以下内容:learn.microsoft.com/en-us/aspnet/core/security/authorization/...

答:

-2赞 Sebastian 2/21/2020 #1

当您在授权管道之外时,不会有。因此,不应使用 内联处理身份验证。AuthorizationFilterContextIAuthorizationService

这似乎正确地遍历了我的所有处理程序,但由于缺少 .AuthorizationFilterContext

听起来您可以控制身份验证处理程序。如果不需要,您是否尝试过在处理程序内部进行短路身份验证?

处理程序可以通过 DI 获取服务,因此您可以通过 IOptionsIHttpContextAccessor 等方式放置所需的运行时配置。

-2赞 zhuber 2/24/2020 #2

您不能创建自己的属性来继承当前属性并在内部解析策略吗?或者更好的是尝试使用AuthorizeIAuthorizationPolicyProvider

class MyPolicyProvider : IAuthorizationPolicyProvider
{
    private DefaultAuthorizationPolicyProvider BackupPolicyProvider { get; }

    public MyPolicyProvider()
    {
        BackupPolicyProvider = new DefaultAuthorizationPolicyProvider(options);
    }

    public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
    {
        if (policyName.Equals("Foo"))
        {
            bool myConditionToAvoidPolicy = true;
            if (myConditionToAvoidPolicy)
            {
                return Task.FromResult<AuthorizationPolicy>(null);
            }
        }

        return BackupPolicyProvider.GetPolicyAsync(policyName);
    }
}

这没有经过测试,但你可以在这里找到更多关于它的信息。

-2赞 curiousBoy 2/26/2020 #3

您的检查条件看起来像在以后发生,我认为这不是一个好主意。您的 api 方法易受攻击,并且在稍后完成检查时仍处于打开状态。但是,通过使用属性,您可以在更早的级别捕获它,并且仍然可以应用自定义逻辑。归根结底,它决定的要么是“是的,可以访问”,要么“不,你没有访问权限!以下未经测试,但应该可以让您继续前进:

public class CustomAuthorize : AuthorizeAttribute
{
    private readonly PermissionAction[] permissionActions;

    public CustomAuthorize(PermissionItem item, params PermissionAction[] permissionActions)
    {
        this.permissionActions = permissionActions;
    }

    public override void OnAuthorization(HttpActionContext actionContext)
    {
        var currentIdentity = System.Threading.Thread.CurrentPrincipal.Identity;
        if (!currentIdentity.IsAuthenticated) {
            // no access
        }

        bool myCondition = "money" == "happiness"; 
        if(myCondition){
           // do your magic here...
        }
        else{
          // another magic...
       }           
    }
}