自个IAuthorizationFilter注射Ninject被执行

问题描述:

在一个项目中我的工作停其他ActionFilterAttribute有哪些使用ninjects BindFilter注入两个自定义ActionFilterAttribute类:自个IAuthorizationFilter注射Ninject被执行

 kernel.BindFilter<LogErrorsAttribute>(FilterScope.Last, 0); 
     kernel.BindFilter<CriticalErrorAttribute>(FilterScope.Last, 1); 

这些已工作的罚款。

我创建一个自定义过滤器个IAuthorizationFilter这是使用BindFilter也注入:

 kernel.BindFilter<AuthorizationFilter>(FilterScope.Action, null).WhenActionMethodHas<Authorise>().WithPropertyValueFromActionAttribute<Authorise>("Roles", n => n.Roles).WithPropertyValueFromActionAttribute<Authorise>("Years", n => n.Years); 

在它自己的,这也能正常工作。

我刚刚发现,如果我将Authorize标签应用于某个操作,则不再调用两个自定义ActionFilterAttribute类。

我难以理解为什么会出现这种情况。我的定制IAuthorizationFilter看起来像这样:

public class AuthorizationFilter : IAuthorizationFilter 
{ 
    private readonly string[] RolesHaveAccessToApplication; 

    public AuthorizationFilter() 
    { 
     //put roles which should allow user to see application, hardcoded for now, but later 
     //this can be generated from the database 
     var configRoles = ConfigurationManager.AppSettings["ApplicationRoles"]; 

     if(string.IsNullOrEmpty(configRoles)) 
      throw new Exception("The ApplicationRoles value has not been defined in the web.config file."); 

     RolesHaveAccessToApplication = configRoles.Split(','); 

    } 

    [Inject] 
    public IUserServices userService { get; set; } 

    public string Roles { get; set; } 
    public string Years { get; set; } 


    protected bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     if (!httpContext.Request.IsAuthenticated) 
      return false; 


     if(!Roles.HasContent() && !Years.HasContent()) 
     { 
      return RolesHaveAccessToApplication.Any(role => RolesHaveAccessToApplication.Any(n => n == role)); 

     } 

     var AuthenticatedUserRoles = System.Web.Security.Roles.GetRolesForUser(); 
     bool isAuthorised = false; 

     //first, lets check against to see if the user has any roles related to the application 
     isAuthorised = RolesHaveAccessToApplication.Any(role => AuthenticatedUserRoles.Any(n => n == role)); 

     //if they don't, we throw them to access denied page 
     if (!isAuthorised) 
      return false; 

     #region CheckRoles 
     if (!string.IsNullOrEmpty(Roles) && AuthenticatedUserRoles.HasContent()) 
     { 
      var authRoles = Roles.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries); 

      isAuthorised = authRoles.Any(role => AuthenticatedUserRoles.Any(n => n == role)); 
     } 
     #endregion 

     #region CheckYears 
     if (!string.IsNullOrEmpty(Years) && AuthenticatedUserRoles.HasContent()) 
     { 


      if (AuthenticatedUserRoles.Any(n => n == "Student")) 
      { 
       var yearRoles = Years.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); 
       var user = userService.FetchUser(httpContext.User.Identity.Name); 
       if (user != null) 
       { 
        isAuthorised = yearRoles.Any(n => n == user.Year); 
       } 
      } 

     } 
     #endregion 

     return isAuthorised; 
    } 

    public void OnAuthorization(AuthorizationContext filterContext) 
    { 
     if(filterContext == null) 
      throw new Exception("filtercontext is null"); 

     if (!filterContext.HttpContext.Request.IsAuthenticated) 
      HandleUnauthorizedRequest(filterContext); 

      if (AuthorizeCore(filterContext.HttpContext)) 
       SetCachePolicy(filterContext); 
      else 
       HandleUnauthorizedRequest(filterContext); 


    } 

    protected void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    { 
     if (filterContext.HttpContext.Request.IsAuthenticated) 
      filterContext.Result = new RedirectResult(new UrlHelper(filterContext.RequestContext).Action("Denied", "Home", new {Area = ""}));// new ViewResult { ViewName = "~/Home/Denied", View = new RazorView("Home") //ViewData = viewData }; 
     else 
      filterContext.Result = new HttpUnauthorizedResult(); 

    } 

    protected void SetCachePolicy(AuthorizationContext filterContext) 
    { 
      ..snip.. 
    } 

} 

//Used as a filter for actions, and ninject is configured to bind AuthorizationFilter to this 
public class Authorise : ActionFilterAttribute 
{ 
    public string Roles { get; set; } 
    public string Years { get; set; } 
} 

任何帮助解决这一点,将不胜感激。

编辑:

这是其他过滤器之一:

public class CriticalErrorAttribute : ActionFilterAttribute 
{ 
    [Inject] 
    public IErrorServices ErrorService { private get; set; } 

    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    {   //if the request is an ajax request, we don't want a redirect to happen 
     //the controller dealing with the ajax request can fetch the critical 
     //errors and pass them back to the user for display 
     if (!filterContext.HttpContext.Request.IsAjaxRequest()) 
     { 
      var criticalErrors = ErrorService.FetchCriticalErrors(); 

      if (criticalErrors.HasContent()) 
      { 
       var helper = new UrlHelper(filterContext.RequestContext); 
       var url = helper.Action("Error", "Home", new { area = "" }); 

       filterContext.Controller.TempData["CriticalErrorList"] = criticalErrors; 

       filterContext.Result = new RedirectResult(url); 
      } 
     } 
     base.OnActionExecuted(filterContext); 
    } 
} 

如果一个域对象不可能是水合,它会记录一个严重错误。这个过滤器会检查这些错误,如果它们发生,它会将用户导向错误页面。

已解决:

事实证明达林是正确的!但是我的配置过滤器隐藏了问题。 首先,我对导航项目进行了[授权],其次我将CriticalErrorAttribute绑定到了每个操作。 所以每次建立菜单(欢迎,左,导航,子) - 这个过滤器正在发射。在这个过滤器调用链的某个时间点,结果被应用于filterContext.Result - 后面的结果隐藏了较早的(正确的)结果。

为了克服这个问题,我调整了CriticalErrorAttribute的BindFilter配置行这样的:

kernel.BindFilter<CriticalErrorAttribute>(FilterScope.Last, 0).When((context, ad) => 
context.RouteData.DataTokens["action"] != null && context.RouteData.DataTokens["action"] != 
"Error" && context.RouteData.DataTokens["controller"] != "Navigation"); 

一切都完美地现在工作!

+0

当其他过滤器不执行时,您的过滤器返回什么? – jgauffin 2012-02-23 13:04:27

+0

我用其他过滤器之一更新了我的问题。 – 2012-02-23 13:14:29

+0

你没有回答我的问题。 – jgauffin 2012-02-23 13:22:34

这里:

filterContext.Result = ... 

您正在分配结果。并根据documentation

您可以取消在OnActionExecuting滤波执行和Result属性设置为一个非空 值 OnResultExecuting方法。任何未决的OnActionExecuted和OnActionExecuting过滤器将不会被调用,并且调用者将不会调用已取消的过滤器或未决过滤器的OnActionExecuted 方法。用于先前运行的过滤器的OnActionExecuted过滤器将运行。将运行OnResultExecuting和OnResultExecuted过滤器的所有 。

+0

嗨达林,我只分配一个结果,如果身份验证失败。所以代码没有被执行。为了检查,我删除了这些代码行,问题仍然存在。 – 2012-02-23 13:11:54

+0

我在我的问题的底部添加了一些文字,可能有所帮助。 – 2012-02-23 13:20:00

+0

嗨达林,你在这个问题上是正确的。调试花了一段时间,但我已将我的解决方案附加到我的答案中。 – 2012-02-29 12:11:20