簡體   English   中英

Anti-Forgery Token適用於不同的基於聲明的用戶

[英]Anti-Forgery Token was meant for a different claims-based user

我正在使用ASP.NET身份登錄的應用程序中的注銷功能。 我可以成功登錄但是當我退出然后嘗試再次登錄時,我收到以下消息:

The provided anti-forgery token was meant for a different claims-based user than the current user.

這是我的注銷代碼:

 public ActionResult Logout()
        {
            SignInManager.Logout();
            return View("Index"); 
        }

**SignInManager.cs**
 public void Logout()
        {
            AuthenticationManager.SignOut(); 
        }

用戶按下注銷按鈕后,他將進入登錄屏幕。 網址仍然顯示“ http:// localhost:8544 / Login / Logout ”。 因為我們在登錄屏幕上,所以它應該只是說“ http:// localhost:8544 / Login ”。

您正在返回一個View ,而不是調用RedirectToAction() 所以發生的事情是視圖在注銷請求的上下文中運行,用戶仍然登錄。在請求完成之前,它們不會被注銷。

所以,試試吧

public ActionResult Logout()
{
    SignInManager.Logout();
    return RedirectToAction("Index", "Home");
}

對我有用的是切換所使用的中間件的順序。 添加第一個app.UseAuthentication() ,然后添加防偽設備。 我就是這樣做的:

app.UseAuthentication();
app.Use(next => ctx =>
        {
            var tokens = antiforgery.GetAndStoreTokens(ctx);

            ctx.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
                new CookieOptions() { HttpOnly = false });

            return next(ctx);
});

反過來創建一個不適合經過身份驗證的用戶的令牌。

嘗試這個:

public ActionResult Logout()
{
    AuthenticationManager.SignOut();
    Session.Abandon();
    return RedirectToAction("Index");
}

這將重新加載您的登錄頁面,該頁面將為您提供新的CSRF令牌。

我現在在登錄時遇到同樣的錯誤,但是一直沒能弄清楚原因。 最后我找到了它,所以我在這里發布它(盡管它有一個稍微不同的原因)以防其他人擁有它。

這是我的代碼:

//
// GET: /login
[OutputCache(NoStore = true, Location = System.Web.UI.OutputCacheLocation.None)]
public ActionResult Login()
{
    return View();
}

//
// POST: /login
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);

    if (!ModelState.IsValid)
    {
        return View(model);
    }
    //etc...

這對於99.99%的登錄工作正常,但是現在我偶然得到了上述錯誤,盡管我無法重現它,直到現在。

只有當有人快速連續兩次單擊登錄按鈕時才會出現此錯誤。 但是,如果我在Login操作中刪除AuthenticationManager.SignOut行,那就沒關系。 我不知道為什么我把那條線放在那里,但它導致了問題 - 並且刪除它修復了問題。

嘗試這個:

 public ActionResult Login(string modelState = null)
    {
        if (modelState != null)
            ModelState.AddModelError("", modelState );

        return View();
    }
 [ValidateAntiForgeryToken]
    public async Task<ActionResult> Login(LoginViewModel model)
    {
        AuthenticationManager.SignOut();

        return RedirectToAction("Login", "Controller", new { modelState = "MSG_USER_NOT_CONFIRMED" });
    }

我沒有像我在Login方法中提到的Sean那樣的AuthenticationManager.SignOut命令。 我可以通過在下一個View加載之前多次單擊登錄按鈕來重現。 我在第一次單擊后禁用了“登錄”按鈕以防止出錯。

<button type="submit" onclick="this.disabled=true;this.form.submit();"/>

我發現用戶在經過身份驗證后提交登錄頁面時遇到此問題。 我通過以下方式復制了此錯誤:

  1. 登錄后打開兩個選項卡,
  2. 從一個登出,
  3. 重新加載,
  4. 登錄到一個,
  5. 試圖用另一個登錄。 在進入POST之前發生錯誤:/帳戶/登錄操作。

我的大多數用戶都使用移動設備上的網絡應用程序,因此有意義的是他們已經將登錄頁面加入書簽並將其提取並在已經登錄的后台打開標簽時提交。我還猜測有時候他們將有一個休眠選項卡加載登錄表單,只需拉出該選項卡並提交。

我意識到有很多方法可以解決這個問題。 我解決了兩個變化:

  1. 我在User.Identity.IsAuthenticated上添加了對我的“GET:/ Account / Login”操作的檢查:
if (User.Identity.IsAuthenticated)
{
   try
   {
      return RedirectToLocal(returnUrl);
   }
   catch
   {
      return RedirectToAction("index", "Home");
   }
}
  1. 在我的控制器中,我創建了一個“檢查是否已登錄”操作:
[AllowAnonymous]
public JsonResult CheckLogedIn()
{
    try
    {
        return Json(new { logged_in = User.Identity.IsAuthenticated }, JsonRequestBehavior.AllowGet);
    }
    catch
    {
        return Json(new { logged_in = false }, JsonRequestBehavior.AllowGet);
    }
}

我在視圖中反復調用它,以便在已經登錄時將所有打開的登錄表單從登錄頁面重定向:

<script type="text/javascript">
    setInterval(function () {
        $.ajax({
                url: '@Url.Action("CheckLogedIn", "Account")',
                type: "GET",
            }).done(function (data) {
                if (data.logged_in) {
                    window.location = '/';
                }
            });
    }, 5000);  
</script>

這對我很有用。 希望它能幫到你。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM