asp.net-mvc MVC 4 AuthorizeAttribute.HandleUnauthorizedRequest ViewResult - 无限循环

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20012795/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 03:19:57  来源:igfitidea点击:

MVC 4 AuthorizeAttribute.HandleUnauthorizedRequest ViewResult - infinite loop

asp.net-mvcasp.net-mvc-4asp.net-authorization

提问by Sonic Soul

i've stepped through my code a million times and can't find a problem with my implementation..

我已经遍历了我的代码一百万次,但在我的实现中找不到问题。

in custom AuthorizeAttribute i overwrote 2 methods

在自定义 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);
     }

the authorization logic is mocked to return false only on specific controller, and i've stepped through this to verify it's working correctly.

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

above code will cause infinite loop. in my log i can see that line hit 666 times (coincidence?) ..

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

if i do call base.HandleUnauthorizedRequest(ctx), all i get is a blank page. so i reflected what the base does, and it's this

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

filterContext.Result = new HttpUnauthorizedResult();

so this explains why it renders a blank page instead of redirecting to Unauthorized.cshtml. what i'm not sure about, is why does it go into an infinite loop if i don't call the base.

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

p.s.

ps

i've verified that if i put the wrong Unauthorized view it will error out (but still hangs indefinitely)

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

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

回答by Sonic Soul

Here is the implementation that i ended up going with and it's working very well.

这是我最终采用的实现,并且运行良好。

    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;
            }
        }
    }

回答by James

The default implementation of AuthorizeAttributesets the response on the action context, by not calling into the base the response is never set which causes the filter to repeat the authorization process until a response is set (hence the infinite loop).

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

You can see this logic in the AuthorizationFilterAttributeclass which AuthorizeAttribute derives from.

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