ASP.NET 5 中的 OverrideAuthorizationAttribute
OverrideAuthorizationAttribute in ASP.NET 5
我想在 MVC6 中实现以下功能:
[Authorize(Roles = "Shopper")]
public class HomeController
{
[Authorize(Roles = "Editor"), OverrideAuthorization]
public IActionResult EditPage() {}
}
但 OverrideAuthorizationAttribute 已不存在。那么如何设置,让用户只需要处于 Editor
角色而不是 Editor
和 Shopper
角色就可以访问 MVC6 中的 EditPage?
我从 Filip W 那里找到了 this blog post,它解释了如何使用过滤器提供程序编写您自己的解决方案。
但是框架已经改变了很多,他的解决方案必须更新以考虑框架中的变化,直到 beta8。
首先,您将创建一个新属性,您可以在其中指定要覆盖的 filter 的类型。 (在你的情况下,这将是 AuthorizeFilter
)
public class OverrideFilter : ActionFilterAttribute
{
public Type Type { get; set; }
}
如果你愿意。您可以创建更具体的过滤器,例如:
public class OverrideAuthorization : OverrideFilter
{
public OverrideAuthorization()
{
this.Type = typeof(AuthorizeFilter);
}
}
然后你需要创建一个新的IFilterProvider
。
- 此过滤器提供程序将在默认提供程序之后执行
该框架有 运行.
- 您可以检查
FilterProviderContext.Results
并搜索您的 OverrideFilter
- 如果找到,您可以检查其余过滤器,然后删除
过滤类型和较低范围的任何过滤器
例如,按照这个想法创建一个新的 OverrideFriendlyFilterProvider
:
public class OverrideFriendlyFilterProvider : IFilterProvider
{
//all framework providers have negative orders, so ours will come later
public int Order => 1;
public void OnProvidersExecuting(FilterProviderContext context)
{
if (context.ActionContext.ActionDescriptor.FilterDescriptors != null)
{
//Does the action have any OverrideFilter?
var overrideFilters = context.Results.Where(filterItem => filterItem.Filter is OverrideFilter).ToArray();
foreach (var overrideFilter in overrideFilters)
{
context.Results.RemoveAll(filterItem =>
//Remove any filter for the type indicated in the OverrideFilter attribute
filterItem.Descriptor.Filter.GetType() == ((OverrideFilter)overrideFilter.Filter).Type &&
//Remove filters with lower scope (ie controller) than the override filter (i.e. action method)
filterItem.Descriptor.Scope < overrideFilter.Descriptor.Scope);
}
}
}
public void OnProvidersExecuted(FilterProviderContext context)
{
}
}
您需要在您的启动 ConfigureServices
上注册它 class:
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IFilterProvider, OverrideFriendlyFilterProvider>());
通过所有这些,您将能够覆盖授权过滤器(或任何其他过滤器)。
例如,在新 mvc 应用程序的默认 HomeController 中,任何登录用户都可以访问 Home 操作,但只有具有管理员角色的用户才能访问能够访问 关于 操作:
[Authorize]
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
[Authorize(Roles = "admin"), OverrideAuthorization]
public IActionResult About()
{
return View();
}
我认为最好使用新的基于策略的授权方法而不是直接使用角色。
目前还没有很多关于基于策略的授权的文档,但this article是一个好的开始
我想在 MVC6 中实现以下功能:
[Authorize(Roles = "Shopper")]
public class HomeController
{
[Authorize(Roles = "Editor"), OverrideAuthorization]
public IActionResult EditPage() {}
}
但 OverrideAuthorizationAttribute 已不存在。那么如何设置,让用户只需要处于 Editor
角色而不是 Editor
和 Shopper
角色就可以访问 MVC6 中的 EditPage?
我从 Filip W 那里找到了 this blog post,它解释了如何使用过滤器提供程序编写您自己的解决方案。
但是框架已经改变了很多,他的解决方案必须更新以考虑框架中的变化,直到 beta8。
首先,您将创建一个新属性,您可以在其中指定要覆盖的 filter 的类型。 (在你的情况下,这将是 AuthorizeFilter
)
public class OverrideFilter : ActionFilterAttribute
{
public Type Type { get; set; }
}
如果你愿意。您可以创建更具体的过滤器,例如:
public class OverrideAuthorization : OverrideFilter
{
public OverrideAuthorization()
{
this.Type = typeof(AuthorizeFilter);
}
}
然后你需要创建一个新的IFilterProvider
。
- 此过滤器提供程序将在默认提供程序之后执行 该框架有 运行.
- 您可以检查
FilterProviderContext.Results
并搜索您的OverrideFilter
- 如果找到,您可以检查其余过滤器,然后删除 过滤类型和较低范围的任何过滤器
例如,按照这个想法创建一个新的 OverrideFriendlyFilterProvider
:
public class OverrideFriendlyFilterProvider : IFilterProvider
{
//all framework providers have negative orders, so ours will come later
public int Order => 1;
public void OnProvidersExecuting(FilterProviderContext context)
{
if (context.ActionContext.ActionDescriptor.FilterDescriptors != null)
{
//Does the action have any OverrideFilter?
var overrideFilters = context.Results.Where(filterItem => filterItem.Filter is OverrideFilter).ToArray();
foreach (var overrideFilter in overrideFilters)
{
context.Results.RemoveAll(filterItem =>
//Remove any filter for the type indicated in the OverrideFilter attribute
filterItem.Descriptor.Filter.GetType() == ((OverrideFilter)overrideFilter.Filter).Type &&
//Remove filters with lower scope (ie controller) than the override filter (i.e. action method)
filterItem.Descriptor.Scope < overrideFilter.Descriptor.Scope);
}
}
}
public void OnProvidersExecuted(FilterProviderContext context)
{
}
}
您需要在您的启动 ConfigureServices
上注册它 class:
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IFilterProvider, OverrideFriendlyFilterProvider>());
通过所有这些,您将能够覆盖授权过滤器(或任何其他过滤器)。
例如,在新 mvc 应用程序的默认 HomeController 中,任何登录用户都可以访问 Home 操作,但只有具有管理员角色的用户才能访问能够访问 关于 操作:
[Authorize]
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
[Authorize(Roles = "admin"), OverrideAuthorization]
public IActionResult About()
{
return View();
}
我认为最好使用新的基于策略的授权方法而不是直接使用角色。
目前还没有很多关于基于策略的授权的文档,但this article是一个好的开始