21

jQuery を使用してコントローラー アクションから部分ビューを読み込むビューがあります。コントローラー アクションは Authorize 属性で装飾されており、適切なログオン ページにリダイレクトされる代わりにそのアクションが呼び出されたときにユーザーがタイムアウトした場合、部分ビューが移動したビューにログオン ページが挿入されます。

jQuery を使用したソリューションを説明する別の投稿がここにありますが、残念ながら、私が必要とするコード サンプルは含まれていません。なぜなら、私は jQuery にあまり詳しくない (そして Web 開発に慣れていない) ため、この問題を解決する必要があるからです。できるだけ早く。

私がやりたいことは、ユーザーを適切なログオン ページにリダイレクトすることだけです。jQuery を使用する方法がある場合は、誰かがコード サンプルを投稿していただけないでしょうか。

ありがとう。

4

2 に答える 2

34

解決策 1、エラーを示す応答を返す


Pro ASP.NET MVC 2 フレームワークは、これに対する 1 つのソリューションを提供します。

Ajax リクエストが認証を拒否された場合、通常はログイン ページに HTTP リダイレクトを返したくありません。クライアント側のコードはそれを予期しておらず、ログイン ページ全体を途中で挿入するなどの望ましくない処理を実行する可能性があるためです。ユーザーが表示しているページの。代わりに、おそらく JSON 形式で、より有用なシグナルをクライアント側コードに送り返し、リクエストが承認されなかったことを説明する必要があります。これは次のように実装できます。

public class EnhancedAuthorizeAttribute : AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(AuthorizationContext context) 
    { 
        if (context.HttpContext.Request.IsAjaxRequest()) { 
            UrlHelper urlHelper = new UrlHelper(context.RequestContext); 
            context.Result = new JsonResult { 
                Data = new { 
                    Error = "NotAuthorized", 
                    LogOnUrl = urlHelper.Action("LogOn", "Account") 
                }, 
                JsonRequestBehavior = JsonRequestBehavior.AllowGet 
            }; 
        } 
        else 
            base.HandleUnauthorizedRequest(context); 
    } 
} 

次に、コントローラーから JSON オブジェクトを取得し、{'Error': 'NotAuthorized', 'LogonUrl': '...'}それを使用してユーザーをリダイレクトします。

また、HTML を期待している場合は、代わりの応答として、プレーンな文字列を返し、NotAuthorized:<your_url>応答がこのパターンに一致するかどうかを確認することもできます。


401 Unautorized解決策 2、ステータス コードを返して処理する


これは、すべての ajax リクエストのsuccessコールバックでチェックする必要があるため、非常に面倒です。このケースをグローバルにキャッチできるといいですね。最善の解決策は、サーバーからステータス コードを返し、401 UnauthorizedjQuery を使用.ajaxErrorしてそれをキャッチすることですが、IIS/ASP.NET では問題があります。これは、応答にこのステータス コードが含まれている場合に、ログイン ページにリダイレクトすることが決定的に行われるためです。このリダイレクト<authentication>にタグが存在する限り、何もしなければ[1]発生します。web.config

では、何とかしましょう。このハッキーな方法は良さそうでした。あなたのglobal.asax.csで

protected void Application_EndRequest()
{
    if (Context.Response.StatusCode == 302 && Context.Request.RequestContext.HttpContext.Request.IsAjaxRequest())
    {
        Context.Response.Clear();
        Context.Response.StatusCode = 401;
    }
}

401(ステータスコードを返すためのより良い方法を誰かが知っているなら、それを聞いてみたいです。)

これにより、リクエストが ajax リクエストの場合にログオン ページにリダイレクトするというデフォルトの動作を防止できます。 したがって、残りは が処理するため、デフォルトAuthorizeAttributeをそのまま使用できます。Application_EndRequest

ここで、jQuery コードで.ajaxError関数を使用してエラーをキャッチします。これはグローバルな ajax イベント ハンドラーです。つまり、任意の ajax 呼び出しによって発生したすべてのエラーをインターセプトします。任意の要素にアタッチできます-私の例ではbody、常に存在する原因を選択しました

$("body").ajaxError(function(event, XMLHttpRequest, ajaxOptions, thrownError) {
    if (XMLHttpRequest.status == 401) {
        alert("unauthorized");
    }
});

このようにして、リダイレクト ロジックを1か所に集中させることができます。


解決策 3、カスタム ヘッダーを返す


この回答は、代替ソリューションを提供します。これは、同じ種類のグローバル イベント ハンドラーを使用しますが、ハック ビットをスキップします。認証されておらず、リクエストが ajax リクエストである場合、ページにカスタム ヘッダーが追加され、各 でこのヘッダーがチェックされます.ajaxComplete。リンクされた回答で提供されている方法は、機密性の高いコンテンツを含む元のビューを返し、javascript に依存してユーザーをそこからリダイレクトするため、安全ではないことに注意してください。ハックを必要とせず、ロジックを 1 つのコールバック関数に集中させることができるため、少し変更すると非常に優れたものになります。私が見ることができる唯一の欠点は、意味的に正しいステータス コードで応答しない200 OKことです。401 Unauthorized


これを別のカスタムに焼き付けることができますEnhancedAuthorizationAttribute

public class EnhancedAuthorizeAttribute : AuthorizeAttribute
{
        protected override void HandleUnauthorizedRequest(AuthorizationContext context)
        {
            if (context.HttpContext.Request.IsAjaxRequest()) 
            {
                context.HttpContext.Response.AddHeader("REQUIRES_AUTH", "1");
                context.Result = new EmptyResult();
            }
            else
            {
                base.HandleUnauthorizedRequest(context);
            }
        }
    }
}

これで、ajax リクエストが完了するたびに、次のヘッダーをチェックします。

$('body').ajaxComplete(function(event,request,settings){
    if (request.getResponseHeader('REQUIRES_AUTH') === '1'){
        alert("unauthorized");
    };
});
于 2010-11-17T02:11:43.867 に答える
3

Simen Echholt の 2 番目のソリューションでは、使用できます

$.ajaxSetup({ global: true,
    statusCode: {
        401: function () {
            alert("unauthorized");
        }
    }
});

ステータスコード401で関数をバインドする

于 2012-04-17T02:36:55.733 に答える