在我的基本控制器中,我有一个OnAuthorization事件处理程序,在我的控制器中,我有处理程序,有时有[Authorize]
,有时没有。这些控制器继承自基本控制器。
我期望的是OnAuthorization在实际需要授权时被触发(方法或控制器具有[Authorize]
)。
情况并非如此,每个方法都会触发OnAuthorization。
是否有一种方法来防止这种情况发生或检测方法/类没有[Authorize]
属性?
目前我只想授权5个或25个左右的处理程序,所以如果有一个方法来处理这个问题,而不必改变所有的控制器,那就太好了。
参见MVC中的过滤。
MVC控制器OnAuthorization
方法功能的原因是因为控制器类实现了IAuthorizationFilter
, MVC使用ControllerInstanceFilterProvider
将所有控制器注册为全局过滤器。
全局授权过滤器在上运行每个请求。由您决定它们是否有资格进行授权检查。如果您希望在AuthorizeAttribute
不存在的情况下执行授权,则需要添加检查AuthorizeAttribute
是否存在的条件,如果存在则跳过自定义授权检查。
protected override void OnAuthorization(AuthorizationContext filterContext)
{
bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AuthorizeAttribute), inherit: true)
|| filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AuthorizeAttribute), inherit: true);
if (skipAuthorization)
{
return;
}
// Do your authorization here...
base.OnAuthorization(filterContext);
}
默认情况下不会发生这种情况的原因是AuthorizeAttribute
是IAuthorizationFilter
的与控制器实例不同的实例。AuthorizeAttribute
既是IAuthorizationFitler
又是FilterAttribute
。当您将放置在一个动作方法上时,它以这样一种方式向框架注册,即它只在该动作方法上执行。另一方面,控制器IAuthorizationFilter
总是全局注册的,因此它在每个请求上运行。这两个授权过滤器彼此完全不知道。
另外,你应该永远不要在MVC中使用基控制器类。对于横切关注点,您可以使用全局注册的过滤器。这就是OnAuthorization
方法在控制器中的工作方式——它是一个全局过滤器。但是,您可以将横切代码分离到过滤器类中,这些过滤器类与您的控制器更加坚固和松散耦合。
您可以使用[AllowAnonymous]
来排除对特定操作/方法的授权的例子:
[AllowAnonymous]
public ActionResult MyAction()
{
}