组合自定义AuthorizeAttribute和RequireHttpsAttribute
本文关键字:RequireHttpsAttribute AuthorizeAttribute 自定义 组合 | 更新日期: 2023-09-27 18:29:18
我在FilterConfig
中应用了一个自定义RequireHttpsAttribute
和自定义AuthorizeAttribute
,以确保所有控制器都使用HTTPS并以相同的方式进行授权。
我还有一个需要其他授权的控制器操作。在这种情况下,我必须首先使用[OverrideAuthorization]
来覆盖全局授权过滤器,然后才能为该操作设置特殊授权。
但是[OverrideAuthorization]
也将覆盖CustomRequireHttpsAttribute
,因为它也源自IAuthorizationFilter
。我可以做些什么,这样我就不必每次重写授权时都读取CustomRequireHttpsAttribute
属性了?
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new CustomRequireHttpsAttribute());
filters.Add(new CustomAuthorizeAttribute(Role = "User"));
}
}
public class MyController : BaseController
{
public ActionResult DoSomeUserStuff()
{
}
[OverrideAuthorization]
[CustomRequireHttpsAttribute]
[CustomAuthorizeAttribute(Role = "Admin")]
public ActionResult DoSomeAdminStuff()
{
}
}
我最终基于这篇文章的修改版本创建了自己的自定义IFilterProvider
。
我添加了一个额外的属性,可以用于那些我想覆盖全局设置的属性的控制器或操作。它实际上只是扩展了CustomAuthorizeAttribute
,使其具有相同的功能:
public class OverrideCustomAuthorizeAttribute : CustomAuthorizeAttribute {}
然后我创建一个IFilterProvider
,它检查过滤器列表中是否存在任何OverrideCustomAuthorizeAttribute
。如果是,请从列表中删除所有CustomAuthorizeAttribute
:
public class CustomFilterProvider : IFilterProvider
{
private readonly FilterProviderCollection _filterProviders;
public CustomFilterProvider(IList<IFilterProvider> filters)
{
_filterProviders = new FilterProviderCollection(filters);
}
public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
var filters = _filterProviders.GetFilters(controllerContext, actionDescriptor).ToArray();
var shouldOverrideCustomAuthorizeAttribute = filters.Any(filter => filter.Instance is OverrideCustomAuthorizeAttribute);
if (shouldOverrideCustomAuthorizeAttribute)
{
// There is an OverrideCustomAuthorizeFilterAttribute present, remove all CustomAuthorizeAttributes from the list of filters
return filters.Where(filter => filter.Instance.GetType() != typeof(CustomAuthorizeAttribute));
}
return filters;
}
}
我在Global.asax.cs
:中注册此IFilterProvider
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
// Some other stuff first....
var providers = FilterProviders.Providers.ToArray();
FilterProviders.Providers.Clear();
FilterProviders.Providers.Add(new CustomFilterProvider(providers));
}
}
我在FilterConfig.cs
中注册全局CustomAuthorizeAttribute
,就像以前一样:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new CustomRequireHttpsAttribute());
filters.Add(new CustomAuthorizeAttribute(Role = "User"));
}
}
不同的是,我在控制器中使用OverrideCustomAuthorizeAttribute
:
public class MyController : BaseController
{
public ActionResult DoSomeUserStuff()
{
}
[OverrideCustomAuthorizeAttribute(Role = "Admin")]
public ActionResult DoSomeAdminStuff()
{
}
}
这样,CustomRequireHttpsAttribute
总是全局设置的,并且从不被覆盖。
根据此页面,您可以在OverrideAuthorizationAttribute.FiltersToOverride
属性中指定要覆盖的过滤器。
public class MyController : BaseController
{
public ActionResult DoSomeUserStuff()
{
}
[OverrideAuthorization(FiltersToOverride = typeof(CustomAuthorizeAttribute))]
[CustomAuthorizeAttribute(Role = "Admin")]
public ActionResult DoSomeAdminStuff()
{
}
}