组合自定义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()
    {
    }
}

组合自定义AuthorizeAttribute和RequireHttpsAttribute

我最终基于这篇文章的修改版本创建了自己的自定义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()
    {
    }
}
相关文章:
  • 没有找到相关文章