2013-05-07 7 views
18

私はMVC 4アプリを持っていて、フォームセッションが終了してからユーザーがログオフしようとするときに問題があります。ログオフしようとすると、提供された偽造トークンはユーザー "XXXX"のものでしたが、現在のユーザーは ""

Ex。 タイムアウトは5分に設定されています。 ユーザーはログインします。 ユーザーは10分間何もしません。 ユーザーは[ログオフ]リンクをクリックします。 ユーザーにエラーが表示されます: "提供された偽造トークンはユーザー" XXXX "のものですが、現在のユーザーは" "です。

ユーザーは、これを回避するために体操をしなければならなかったので、再ログインしてログアウトすることができます(ログアウトは、その日のタイムカードを閉じるために使用されています)。

私はこれがなぜ起こるのか理解していると思いますが、それを修正する方法がわかりません。

編集: これは、もともとページが読み込まれたときに元々ログインしていたユーザーのためにAntiForgeryトークンが生成されたためです。しかし、セッションが終了してログオフページに移動しようとすると、現在のユーザーは実際のユーザーではなく ""になります。したがって、不一致があり、エラーがレンダリングされます。

+0

エラーが発生した理由を、あなたの仮説を共有することはできますか? – J0e3gan

+0

[関連の投稿](http://stackoverflow.com/questions/14970102/anti-forgery-token-is-meant-for-user-but-the-current-user-is-username)は価値があるようです。 – J0e3gan

+0

私の仮説を追加しました。あなたが参照した投稿を見ましたが、それは関連しているかもしれませんが、私は点を接続することができません...私はASP.NETのこの側面に精通していません。 –

答えて

22

実際にまた、あなたが[HandleError(ExceptionType=typeof(HttpAntiForgeryException)...]を使用することができます/Account/Login

public class HandleAntiForgeryError : ActionFilterAttribute, IExceptionFilter 
{ 
    #region IExceptionFilter Members 

    public void OnException(ExceptionContext filterContext) 
    { 
     var exception = filterContext.Exception as HttpAntiForgeryException; 
     if (exception != null) 
     { 
      var routeValues = new RouteValueDictionary(); 
      routeValues["controller"] = "Account"; 
      routeValues["action"] = "Login"; 
      filterContext.Result = new RedirectToRouteResult(routeValues); 
      filterContext.ExceptionHandled = true; 
     } 
    } 

    #endregion 
} 

[HandleAntiForgeryError] 
[ValidateAntiForgeryToken] 
public ActionResult LogOff() 
{ 
} 

にリダイレクトすること、IExceptionFilterでそれを扱うことができますが、それはのcustomErrorsオンが必要です。

+0

優秀!ちょうど私が感謝の必要なもの! –

+0

これは答えとしてマークされていないと私は信じられません。この回答は信じられないほどです。 –

+1

これは価値があるのですが、これは私のためには機能しません。私がログオフすると、アプリケーションは同じエラーでbarfsします。ただし、例外の型はHttpAntiforgeryExceptionの代わりにInvalidOperationExceptionです。これは非常に一般的なので、これを簡単に処理することは危険です:/ – Sinaesthetic

2

@cemの回答は本当に役に立ちました。私はantiforgerytokenと期限切れのセッションでajax呼び出しのシナリオを含めるために小さな変更を追加しました。

public void OnException(ExceptionContext filterContext) 
{ 
    var exception = filterContext.Exception as HttpAntiForgeryException; 
    if (exception == null) return; 

    if (filterContext.HttpContext.Request.IsAjaxRequest()) 
    { 
     filterContext.HttpContext.Response.StatusCode = 403; 
     filterContext.ExceptionHandled = true; 
    } 
    else 
    { 
     var routeValues = new RouteValueDictionary 
     { 
      ["controller"] = "Account", 
      ["action"] = "Login" 
     }; 
     filterContext.Result = new RedirectToRouteResult(routeValues); 
     filterContext.ExceptionHandled = true; 
    } 
} 

...と、クライアント側で使用すると、ログイン画面にリダイレクトするグローバルAjaxのエラーハンドラを追加することができます...

$.ajaxSetup({ 
    error: function (x) { 
     if (x.status === 403) { 
      window.location = "/Account/Login"; 
     } 
    } 
}); 
関連する問題