方法上的多个授权属性

ada*_*mse 34 c# asp.net-mvc asp.net-core

我在类方法上指定两个单独的Authorization属性时遇到问题:如果两个属性中的任何一个为true,则允许用户访问.

Athorization类看起来像这样:

[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
public class AuthAttribute : AuthorizeAttribute {
. . .
Run Code Online (Sandbox Code Playgroud)

和行动:

[Auth(Roles = AuthRole.SuperAdministrator)]
[Auth(Roles = AuthRole.Administrator, Module = ModuleID.SomeModule)]
public ActionResult Index() {
    return View(GetIndexViewModel());
}
Run Code Online (Sandbox Code Playgroud)

有没有办法解决这个问题,还是我需要重新考虑我的方法?

这将在MVC2中运行.

Dax*_*xxy 47

在更高版本的asp.net中有更好的方法可以在角色上同时执行OR和AND.这是通过约定完成的,在单个Authorize中列出多个角色将执行OR,其中添加多个授权属性将执行AND.

或者例子

[Authorize(Roles = "PowerUser,ControlPanelUser")] 
Run Code Online (Sandbox Code Playgroud)

和例子

[Authorize(Roles = "PowerUser")]
[Authorize(Roles = "ControlPanelUser")]
Run Code Online (Sandbox Code Playgroud)

您可以在以下链接中找到更多相关信息 :https://docs.microsoft.com/en-us/aspnet/core/security/authorization/roles

  • OR 示例也适用于 .NET Framework(非核心)! (2认同)

Jak*_*cki 31

AuthorizeAttributeMVC处理多个实例,就好像它们已加入一样AND.如果你想要一个OR行为,你需要实现自己的检查逻辑.优选地,实现AuthAttribute以承担多个角色并利用OR逻辑执行自己的检查.

另一个解决方案是使用标准AuthorizeAttribute和实现自定义IPrincipal,它将实现bool IsInRole(string role)提供"OR"行为的方法.

这里有一个例子:https: //stackoverflow.com/a/10754108/449906

  • 您无法创建接受其他属性实例的属性.属性类构造函数只能接受编译时有效值/基元类型.这就是为什么`AuthorizeAttribute`将角色作为字符串. (2认同)
  • 有人可以提供官方文档的参考,该文档支持多个“AuthorizeAttribute”实例被处理为逻辑“AND”的声明。在我自己的测试中,过滤器的顺序似乎很重要,第一个过滤器对身份验证是否成功有最终决定权。 (2认同)

小智 5

我已经在生产环境中使用这个解决方案有一段时间了,使用 .NET Core 3.0。我想要自定义属性和本机AuthorizeAttribute. 为此,我实现了IAuthorizationEvaluator接口,一旦所有授权人评估他们的结果,就会调用该接口。

/// <summary>
/// Responsible for evaluating if authorization was successful or not, after execution of
/// authorization handler pipelines.
/// This class was implemented because MVC default behavior is to apply an AND behavior
/// with the result of each authorization handler. But to allow our API to have multiple
/// authorization handlers, in which the final authorization result is if ANY handlers return
/// true, the class <cref name="IAuthorizationEvaluator" /> had to be extended to add this
/// OR behavior.
/// </summary>
public class CustomAuthorizationEvaluator : IAuthorizationEvaluator
{
    /// <summary>
    /// Evaluates the results of all authorization handlers called in the pipeline.
    /// Will fail if: at least ONE authorization handler calls context.Fail() OR none of
    /// authorization handlers call context.Success().
    /// Will succeed if: at least one authorization handler calls context.Success().
    /// </summary>
    /// <param name="context">Shared context among handlers.</param>
    /// <returns>Authorization result.</returns>
    public AuthorizationResult Evaluate(AuthorizationHandlerContext context)
    {
        // If context.Fail() got called in ANY of the authorization handlers:
        if (context.HasFailed == true)
        {
            return AuthorizationResult.Failed(AuthorizationFailure.ExplicitFail());
        }

        // If none handler called context.Fail(), some of them could have called
        // context.Success(). MVC treats the context.HasSucceeded with an AND behavior,
        // meaning that if one of the custom authorization handlers have called 
        // context.Success() and others didn't, the property context.HasSucceeded will be
        // false. Thus, this class is responsible for applying the OR behavior instead of
        // the default AND.

        bool success = 
            context.PendingRequirements.Count() < context.Requirements.Count();

        return success == true 
            ? AuthorizationResult.Success()
            : AuthorizationResult.Failed(AuthorizationFailure.ExplicitFail());
    }
}
Run Code Online (Sandbox Code Playgroud)

仅当添加到 .NET 服务集合(在您的启动类中)时才会调用此评估器,如下所示:

services.AddSingleton<IAuthorizationEvaluator, CustomAuthorizationEvaluator>();
Run Code Online (Sandbox Code Playgroud)

在控制器类中,用这两个属性装饰每个方法。在我的情况[Authorize][CustomAuthorize].