9

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

在自定义 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。我不确定的是,如果我不调用基地,为什么它会进入无限循环。

ps

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

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

2 回答 2

16

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

    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;
            }
        }
    }
于 2014-06-10T16:55:17.197 回答
6

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

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

于 2013-11-16T00:34:45.320 回答