覆盖控制器AuthorizeAttribute只执行一个操作

Dav*_*enn 61 asp.net-mvc

我有一个用AuthorizeAttribute修饰的控制器.除了一个需要CustomAuthorizeAttribute提供的自定义身份验证的操作外,控制器还包含几个需要身份验证的操作.

我的问题是,一旦我在控制器级别添加[授权],我可以使用[CustomAuthorize]仅在一个操作上覆盖它(或删除它)吗?或者我是否必须从控制器级别删除[授权]并将其单独添加到其他每个操作?

我纯粹是为了方便,因为我很懒,不想用AuthorizeAttribute来装饰每一个动作.

[Authorize]
public class MyController : Controller {

  //requires authentication
  public ViewResult Admin() {
    return View();
  }

  //... a lot more actions requiring authentication

  //requires custom authentication
  [CustomAuthorize]  //never invoked as already failed at controller level
  public ViewResult Home() {
    return View();
  }

}
Run Code Online (Sandbox Code Playgroud)

Fra*_*ein 105

在MVC 5中,您可以使用新属性OverrideAuthorization覆盖任何操作的授权.基本上,您将其添加到具有与控制器中定义的授权配置不同的授权配置的操作.

你这样做:

[OverrideAuthorization]
[Authorize(Roles = "Employee")]
public ActionResult List() { ... }
Run Code Online (Sandbox Code Playgroud)

更多信息,请访问http://www.c-sharpcorner.com/UploadFile/ff2f08/filter-overrides-in-Asp-Net-mvc-5/

在ASP.NET Core 2.1中,没有OverrideAuthorization属性,你唯一能做的就是匿名操作,即使控制器没有.有关详细信息,访问https://docs.microsoft.com/en-us/aspnet/core/security/authorization/roles?view=aspnetcore-2.1

一种选择是这样做:

[Authorize(Roles = "Admin,Employee")] // admin or employee
public class XController : Controller 
{
    [Authorize(Roles = "Admin")] // only admin
    public ActionResult ActionX() { ... }

    [AllowAnonymous] // anyone
    public ActionResult ActionX() { ... }
}
Run Code Online (Sandbox Code Playgroud)

  • 这很好用,我认为它应该是选定的答案. (6认同)
  • 完美,正是需要的! (3认同)
  • *Asp.Net Core* 中是否有类似的东西? (3认同)
  • 我编辑了我的答案,添加了有关ASP.NET Core的信息. (3认同)

tva*_*son 27

您可以更改运行属性的顺序(使用Order属性),但我相信在这种情况下,除非生成立即生效的结果,否则它们仍然会运行.关键是在最高级别(类)应用限制性最小的属性,并对方法进行更严格的限制.例如,如果您希望将Home操作公开,则需要从类中删除Authorize属性,并将其应用于其他每个方法.

如果动作具有相同的允许水平,但具有不同的结果,则更改顺序可能就足够了.例如,您通常会重定向到该Logon操作,但是Home您想要重定向到该About操作.在这种情况下,case给出class属性Order=2Homeaction属性Order=1.


bma*_*ity 12

经过太多时间,我想出了一个解决方案.您需要使用自定义AuthorizeAttribute来装饰控制器.

public class OverridableAuthorize : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var action = filterContext.ActionDescriptor;
        if(action.IsDefined(typeof(IgnoreAuthorization), true)) return;

        var controller = action.ControllerDescriptor;
        if(controller.IsDefined(typeof(IgnoreAuthorization), true)) return;

        base.OnAuthorization(filterContext);
    }
}
Run Code Online (Sandbox Code Playgroud)

哪个可以与AllowAnonymous动作配对

[AllowAnonymous]
Run Code Online (Sandbox Code Playgroud)

  • `IgnoreAuthorization`?你的意思是'AllowAnonymous`? (3认同)

Mem*_*per 10

您需要从控制器覆盖[ Authorize ] ,对于特定操作,只需添加

[AllowAnonymous] 
Run Code Online (Sandbox Code Playgroud)

您希望不被授权的操作(然后根据需要添加您的自定义属性)。

请参阅评论/智能感知:

表示一个属性,该属性标记控制器和操作以在授权期间跳过 System.Web.Mvc.AuthorizeAttribute。

完整示例

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Diagnostics;
using System.Threading.Tasks;

namespace Website
{
    public class CustomAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationFilterContext context)
        {
            if (true)//Perform own authorization logic
                return; //simply return if request is authorized

            context.Result = new UnauthorizedResult();
            return; //this is not authorized
        }
    }

    [Authorize]
    public class WebsiteController : Controller
    {
        [HttpGet]
        [AllowAnonymous]//When this is added our Custom Attribute is hit, without it our attribute is not used as request already gets 401 from controller's Authorize
        [CustomAuthorize]
        public IActionResult Index()
        {
            return View(new ViewModel());
        }
}
Run Code Online (Sandbox Code Playgroud)

笔记

如果您想在操作上使用标准[Authorize] 属性并使用自定义策略,例如

[Authorize]
public class WebsiteController : Controller
{
    [HttpGet]
    [AllowAnonymous]
    [Authorize("CustomPolicyName")] //Will not be run
    public IActionResult Index()
    {
        return View(new ViewModel());
    }
}


services.AddAuthorization(options =>
{
    options.AddPolicy("BadgeEntry", policy =>
    policy.RequireAssertion(context =>
        false //Custom logic here
    ));
});
Run Code Online (Sandbox Code Playgroud)

...但是如果像OP一样你想要一个自定义属性那么你就可以使用我的解决方案。