4

多数の Ajax アクションを含むページを持つ ASP.Net MVC4 アプリケーションがあります。セッションの有効期限が切れた後に何が起こるかを処理しようとしています。

現在、コンテキストが現在のリクエスト isAuthenticated を報告する場合、Session_Start() で実行されている「FormsAuthentication.SignOut()」を強制するコードがあります。

protected void Session_Start(object sender, EventArgs e) {
    if (HttpContext.Current.Request.IsAuthenticated) {
        FormsAuthentication.SignOut();         // Drop all the information held in the session
        // now continue with request....
    }
}

次の部分は「HandleUnauthorizedRequest」のオーバーライドです。これは Unauthorized リクエストをトラップし、それが ajax リクエストかどうかをテストし、そうでない場合は続行しますが、それ以外の場合は失敗を示す特定の JSON を返します。

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) {
    if (filterContext.HttpContext.Request.IsAjaxRequest()) {
        filterContext.Result = new JsonResult { Data = new { ajaxUnauthorizedMessage = "sorry, but your session has expired..." }, JsonRequestBehavior = JsonRequestBehavior.AllowGet};
    } else {
        base.HandleUnauthorizedRequest(filterContext);
    }
}

最後に、グローバル jquery ajaxSuccess ハンドラーを用意しました。これは、上記のメッセージをテストし、ユーザーに問題を警告し、リロードを強制します (これにより、MVC がログイン ページにリダイレクトされるはずです)。

$(document).ajaxSuccess(function (result) {
    if (result.ajaxUnauthorizedMessage) {
        alert(result.ajaxUnauthorizedMessage);
        location.reload();
    }
});

残念ながら、そのようには機能しないようです。代わりに発生するのは、セッション開始の「サインアウト」であり、続いて [Authorize] 装飾されたアクション メソッドが実行されます (その後、失われたセッションへの依存が原因で失敗します)。

困ったことに、同じ Ajax 操作に対して 2 回目の呼び出しを (新しいセッションでのタイムアウトを待たずに) 行うと、2 回目の呼び出しは "HandleUnauthorizedRequest" メソッドによってインターセプトされ、最初の呼び出しで期待したとおりにすべてが機能します。まあ、すべてではありませんが、最初の呼び出しをキャッチした後でも、ajaxSuccess グローバル ハンドラーは 2 番目の呼び出しを取得できませんが、これは、主要な問題が解決された後で心配する必要があります)。

さらに、ajax がなくても同じ動作が見られます。サインアウトが発生しますが、私は「事前承認」されているため、とにかくアクションが発生します。

期待どおりに「HandleUnauthorizedRequest」が起動するように、どうすれば正常に認証を解除できますか?

編集 1

気まぐれに、Session_Start() を編集して、すべてのリクエスト Cookie とレスポンス Cookie を削除しました。auth-required Action メソッドがまだ起動していることに驚き、Cookie がすべて元に戻ったことにさらに驚きました! 削除後も存続していました! Session_Start は実際の Request オブジェクトを扱っていないと思いますか? とにかく、試してみる価値がありました。

4

1 に答える 1

0

私はあなたとは少し違った方法でこれに取り組みました。私のソリューションの仕組みは次のとおりです。

「true」または「false」の JSON 応答を返すAuthメソッドを作成しましたAccountController

[AllowAnonymous]
[DoNotResetAuthCookie]
[OutputCache(NoStore=true, Duration=0)]
public JsonResult Auth()
{
    return Json(Request.IsAuthenticated, JsonRequestBehavior.AllowGet);
}

私はあなたが実装したものと同じSession_Start()ものを実装しました。

最後に、私の JavaScript で、まだ認証されているかどうかを定期的に確認し、認証されていない場合は、次のようにページをリダイレクトしました。

function redirectOnNotAuthorized(authUrl, redirectUrl) {
    $.get(authUrl)
         .done(function (data) {
             var isStillAuthorized = data || false;
             if (!isStillAuthorized) {
                 window.location.href = redirectUrl;
             }
         })
        .fail(function () {
            window.location.href = redirectUrl;
        });
}

$(function() {
    var timer, duration;
    duration = 20000;
    window.stillAuthorized = function stillAuthorized() {
        if (timer) {
            clearTimeout(timer);
        }
        timer = setTimeout(stillAuthorized, duration);
        redirectOnNotAuthorized("Account/Auth", "Account/LogOn");
    };
    timer = setTimeout(stillAuthorized, duration);
});

編集1

私は何かを学びました...redirectOnNotAuthorized関数では、設定することも機能します

windows.location.reload()

それ以外の

windows.location.href = redirectUrl;

これにより、コードが簡素化され、アプリへの依存度が低くなります。

于 2013-05-02T16:13:58.440 に答える