Anti-Forgery Token适用于不同的基于声明的用户

时间:2016-03-25 16:53:19

标签: asp.net asp.net-mvc

我正在使用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”。

7 个答案:

答案 0 :(得分:12)

您将返回View,而不是致电RedirectToAction()。所以发生的事情是视图在注销请求的上下文中运行,用户仍然登录。在请求完成之前,他们不会被注销。

所以,试试

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

答案 1 :(得分:8)

对我有用的是切换所使用的中间件的顺序。首先添加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);
});

反过来创建一个不适合经过身份验证的用户的令牌。

答案 2 :(得分:7)

试试这个:

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

这将重新加载您的登录页面,该页面将为您提供新的CSRF令牌。

答案 3 :(得分:4)

我在登录时遇到同样的错误已经很长时间了,但还是找不到原因。最后我发现了它,所以我在这里发布它(尽管它有一个稍微不同的原因)以防其他人拥有它。

这是我的代码:

AuthenticationManager.SignOut

99.99%的登录工作正常,但现在和然后我得到了上述错误,虽然我无法重现它,直到现在。

只有当有人快速连续两次点击登录按钮时才会出现错误。但是,如果我删除了Login操作中的{{1}}行,那就没关系了。我不知道为什么我把那条线放在那里,但它导致了问题 - 并且删除它修复了问题。

答案 4 :(得分:0)

尝试一下:

 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" });
    }

答案 5 :(得分:0)

我没有我的Login方法中提到的AuthenticationManager.SignOut命令。在下一次加载View之前,我可以多次单击登录按钮来进行复制。第一次单击后,我禁用了登录按钮,以防止出现该错误。

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

答案 6 :(得分:0)

我发现用户在通过身份验证后提交登录页面时遇到了此问题。我通过以下方式复制了此错误:

  1. 登录时打开两个标签,
  2. 从其中一个注销,
  3. 同时重新加载
  4. 登录到一个,
  5. 尝试与他人登录。在输入POST:/ Account / Login操作之前发生了错误。

我的大多数用户都在移动设备上使用该Web应用程序,因此在已经登录后台打开标签页的情况下,他们已经将登录页面添加为书签并将其拉出并提交是有意义的。我还推测有时他们会在休眠表单中加载登录表单,然后向上拉并提交该表单。

我意识到有很多方法可以解决此问题。我通过两个更改解决了这个问题:

  1. 我在“ GET:/ Account / Login”操作中添加了对User.Identity.IsAuthenticated的支票:
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>

这对我来说很好。希望对您有帮助。