ASP.NET 控制器 class 和方法上的 MVC 4 自定义授权过滤器
ASP.NET MVC 4 Custom Authorize filter on Controller class and Method
我确实看到了这个 WhosebugQuestion 但这与使用 Authorize 属性有关。我通过扩展 AuthorizeAttribute 使用自定义授权属性。
我希望能够将此自定义过滤器放置在控制器的顶层 class,但是对于一些方法,只强制执行特定角色,而不是同时执行顶层和操作方法角色。
所以,
[AuthorizeUser("Transact")]
public class HomeController : Controller
{
//
// GET: /Search/Home/
public ActionResult Index()
{
return View();
}
[AuthorizeUser("Search")]
public ActionResult Search()
{
return View();
}
}
执行此操作时,框架将检查用户是否同时具有交易和搜索角色。在这种情况下,我只想检查搜索角色。
我正在另一个区域中重复使用此搜索功能和部分视图。
回到我发布的link:WhosebugQuestion我能够让它在我的情况下工作。似乎正在发生的是对我的操作的调用首先从控制器级别查看属性,但是在 OnAuthroization 方法中使用 filterContext.ActionDescriptor.IsDefined 会告诉我被调用的操作是否附加了我的覆盖属性。如果它跳过调用 base.OnAuthorization 方法,那么将调用 override 属性。
因此,我必须做的是创建覆盖 class 并扩展我的自定义授权 class。我在父级中声明了一个标志并在覆盖 class 的构造函数中设置,以告诉我覆盖授权方法是否正在调用我的自定义授权 class 的授权方法。
这里有一个例子来说明这一切。
public class AuthorizeUserAttribute : AuthorizeAttribute
{
protected bool isOverrideAuthorize = false;
public AuthorizeUserAttribute(params...)
{
}
public AuthorizeUserAttribute(MenuItems...)
{
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
var action = filterContext.ActionDescriptor;
if (action.IsDefined(typeof(OverrideAuthorizeUserAttribute), true) && !isOverrideAuthorize)
{
return;
}
base.OnAuthorization(filterContext);
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
}
}
覆盖class:
public class OverrideAuthorizeUserAttribute : AuthorizeUserAttribute
{
public OverrideAuthorizeUserAttribute(params...) : base(roles)
{
base.isOverrideAuthorize = true;
}
public OverrideAuthorizeUserAttribute(MenuItems...) : base(item)
{
base.isOverrideAuthorize = true;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
return base.AuthorizeCore(httpContext);
}
}
这让我可以仅根据在该操作上声明的授权属性对操作进行授权,而不是框架默认的控制器和操作方法上的授权属性。
此外,MVC5 似乎通过包含 "OverrideAuthorization" 属性解决了这个问题。不幸的是,我仍在使用 MVC4。
您可以像下面这样尝试在控制器的顶部,这将支持单个控制器的多个角色,或者您可以使用相同的 Authorize(Roles = "Admin") 过滤每个操作的顶部....
[Authorize(Roles = "Admin,HRManager,Finance")]
Public class MyController:Controller{
// inside controller action methods
}
我确实看到了这个 WhosebugQuestion 但这与使用 Authorize 属性有关。我通过扩展 AuthorizeAttribute 使用自定义授权属性。
我希望能够将此自定义过滤器放置在控制器的顶层 class,但是对于一些方法,只强制执行特定角色,而不是同时执行顶层和操作方法角色。
所以,
[AuthorizeUser("Transact")]
public class HomeController : Controller
{
//
// GET: /Search/Home/
public ActionResult Index()
{
return View();
}
[AuthorizeUser("Search")]
public ActionResult Search()
{
return View();
}
}
执行此操作时,框架将检查用户是否同时具有交易和搜索角色。在这种情况下,我只想检查搜索角色。
我正在另一个区域中重复使用此搜索功能和部分视图。
回到我发布的link:WhosebugQuestion我能够让它在我的情况下工作。似乎正在发生的是对我的操作的调用首先从控制器级别查看属性,但是在 OnAuthroization 方法中使用 filterContext.ActionDescriptor.IsDefined 会告诉我被调用的操作是否附加了我的覆盖属性。如果它跳过调用 base.OnAuthorization 方法,那么将调用 override 属性。
因此,我必须做的是创建覆盖 class 并扩展我的自定义授权 class。我在父级中声明了一个标志并在覆盖 class 的构造函数中设置,以告诉我覆盖授权方法是否正在调用我的自定义授权 class 的授权方法。
这里有一个例子来说明这一切。
public class AuthorizeUserAttribute : AuthorizeAttribute
{
protected bool isOverrideAuthorize = false;
public AuthorizeUserAttribute(params...)
{
}
public AuthorizeUserAttribute(MenuItems...)
{
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
var action = filterContext.ActionDescriptor;
if (action.IsDefined(typeof(OverrideAuthorizeUserAttribute), true) && !isOverrideAuthorize)
{
return;
}
base.OnAuthorization(filterContext);
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
}
}
覆盖class:
public class OverrideAuthorizeUserAttribute : AuthorizeUserAttribute
{
public OverrideAuthorizeUserAttribute(params...) : base(roles)
{
base.isOverrideAuthorize = true;
}
public OverrideAuthorizeUserAttribute(MenuItems...) : base(item)
{
base.isOverrideAuthorize = true;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
return base.AuthorizeCore(httpContext);
}
}
这让我可以仅根据在该操作上声明的授权属性对操作进行授权,而不是框架默认的控制器和操作方法上的授权属性。
此外,MVC5 似乎通过包含 "OverrideAuthorization" 属性解决了这个问题。不幸的是,我仍在使用 MVC4。
您可以像下面这样尝试在控制器的顶部,这将支持单个控制器的多个角色,或者您可以使用相同的 Authorize(Roles = "Admin") 过滤每个操作的顶部....
[Authorize(Roles = "Admin,HRManager,Finance")]
Public class MyController:Controller{
// inside controller action methods
}