我看到尽可能多的答案,但他们似乎没有一个细节.
麻烦的是将操作过滤器(由控制器注入的服务)绑定到相应的属性时,我一直无法弄清楚如何将参数/属性值从属性传递到其绑定的过滤器.下面是代码,下面是我想要的假码:
过滤器属性
public class AuthorizationFilter : IAuthorizationFilter { private readonly IAuthorizationService _authorizationService; private readonly UserRoles _requiredRoles; // Enum public AuthorizationFilter(IAuthorizationService authorizationService,UserRoles requiredRoles) { _authorizationService = authorizationService; _requiredRoles = requiredRoles; } public void OnAuthorization(AuthorizationContext filterContext) { if (filterContext.HttpContext.Session == null) HandleUnauthorizedRequest(filterContext); else { var authorized = _authorizationService.IsUserInRole((UserSessionInfoviewmodel) filterContext.HttpContext.Session["user"],_requiredRoles); if (!authorized) HandleUnauthorizedRequest(filterContext); // else TODO: deal with cache... } } } public class RequireRolesAttribute : FilterAttribute { public readonly UserRoles requiredRoles; public RequireRolesAttribute(UserRoles requiredRoles) { requiredRoles = requiredRoles; } }
过滤器/属性绑定
kernel.BindFilter<AuthorizationFilter>(FilterScope.Controller,0) .WhenControllerHas<RequireRolesAttribute>(); kernel.BindFilter<AuthorizationFilter>(FilterScope.Action,0) .WhenActionMethodHas<RequireRolesAttribute>();
这应该确保用[Rolesrequired]装饰的任何控制器/动作绑定到过滤器.到现在为止还挺好.现在我想通过属性声明角色(很像股票AuthorizeAttribute),并将这些值传递给实际执行授权的过滤器.
预期/伪造代码:
[RequireRoles(UserRoles.Author)] public ActionResult Index() { // blah }
特别,
通知AuthorizationFilter角色需要做些什么?过滤器/ ninject可以访问传递给属性的构造函数的参数吗?过滤器/ ninject可以从属性public属性中拉出它们吗?
作为参考,这些文章是一个巨大的帮助,但不要回答这一件事:
Dependency Injection with Ninject and Filter attribute for asp.net mvc
Custom Authorization MVC 3 and Ninject IoC
B Z,Remo Gloor,其他…我该如何完成这个?
解决方法
我已经弄清楚了(谢谢雷姆的指示和文件).
使用适当的.WithConstructorArgument扩展,无论您是绑定到Controller还是Action过滤器.例如绑定我的动作过滤器,如下所示:
kernel.BindFilter<AuthorizationFilter>(FilterScope.Action,0) .WhenActionMethodHas<RequireRolesAttribute>() .WithConstructorArgumentFromActionAttribute<RequireRolesAttribute>("requiredRoles",o => o.requiredRoles);
一旦我明白了Func<>签名,一切都变得清晰.我发现处理这个最好的方法是
>使我的属性的扩展类型特定
.WithConstructorArgumentFromActionAttribute<TAttribute>()
("argumentName",o => o.PropertyName)