【问题标题】:MVC 4 AuthorizeAttribute.HandleUnauthorizedRequest ViewResult - infinite loopMVC 4 AuthorizeAttribute.HandleUnauthorizedRequest ViewResult - 无限循环
【发布时间】:2013-11-29 12:54:22
【问题描述】:

我已经通过我的代码一百万次,找不到我的实现问题..

在自定义 AuthorizeAttribute 中我覆盖了 2 个方法

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (!httpContext.Request.IsAuthenticated)
            return false;
        var routeData = httpContext.Request.RequestContext.RouteData;
        var ctrl = routeData.Values["controller"].ToString();
        var action = routeData.Values["action"].ToString();
        var user = httpContext.User.Identity.Name;
        _logger.Info("[logging all the details]");
        return ctrl == "SomeController";
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext ctx)
    {
        ctx.Result = new ViewResult  { ViewName = "Unauthorized" };
        // base.HandleUnauthorizedRequest(ctx);
     }

授权逻辑被模拟为仅在特定控制器上返回 false,我已经逐步验证它是否正常工作。

以上代码会导致无限循环。在我的日志中,我可以看到那条线命中了 666 次(巧合?)..

如果我调用 base.HandleUnauthorizedRequest(ctx),我得到的只是一个空白页。所以我反映了基地的作用,就是这个

filterContext.Result = new HttpUnauthorizedResult();

所以这解释了为什么它呈现一个空白页面而不是重定向到 Unauthorized.cshtml。我不确定的是,如果我不调用基地,为什么它会进入无限循环。

附言

我已经验证,如果我放错未经授权的视图,它会出错(但仍会无限期挂起)

 System.InvalidOperationException: The view 'Unauthorized11' or its master was not found or no view engine supports the searched locations

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-4 asp.net-authorization


    【解决方案1】:

    AuthorizeAttribute 的默认实现在动作上下文中设置响应,通过不调用基础响应永远不会设置,这会导致过滤器重复授权过程,直到设置响应(因此是无限循环)。

    您可以在 AuthorizeAttribute 派生自的 AuthorizationFilterAttribute 类中看到此逻辑。

    【讨论】:

      【解决方案2】:

      这是我最终使用的实现,它运行良好。

          public override void OnAuthorization(AuthorizationContext filterContext)
          {
      
              base.OnAuthorization(filterContext);
      
              // this is overriden for kendo menus to hide 
              var ctrl = filterContext.RequestContext.RouteData.GetRequiredString("controller");
              var action = filterContext.ActionDescriptor.ActionName;
      
              [custom authorization logic on action/ctrl]
      
              // useful to determine if it's authorizing current controller path or menu links
              var path = filterContext.HttpContext.Request.PhysicalPath;
              _authorizingCurrentPath = path.Contains(ctrl) || path.EndsWith("WebUI") ;
      
      
              if (userAuth < requiredAuth)
                  HandleUnauthorizedRequest(filterContext);
          }
      
      
          protected override void HandleUnauthorizedRequest(AuthorizationContext ctx)
          {
              if (!ctx.HttpContext.User.Identity.IsAuthenticated)
                  base.HandleUnauthorizedRequest(ctx);
              else {
                  if (_authorizingCurrentPath) {
                      // handle controller access
                      ctx.Result = new ViewResult { ViewName = "Unauthorized" };
                      ctx.HttpContext.Response.StatusCode = 403;
                  }
                  else {
                      // handle menu links
                      ctx.Result = new HttpUnauthorizedResult();
                      ctx.HttpContext.Response.StatusCode = 403;
                  }
              }
          }
      

      【讨论】:

      • 变量 if (userAuth
      • @AbhishekB。它是一个枚举,具有底层 int .. 所以 read = 5, full = 10 等.. 所以你可以做 currentAtrr > read etc
      • 好的。它有帮助。我正在使用带有角色的会话对象。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-27
      • 2018-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多