解決策 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 Unauthorized
jQuery を使用.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");
};
});