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

間違った Unauthorized ビューを配置すると、エラーが発生することを確認しました (ただし、無期限にハングアップします)。

 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 に答える