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

joh*_*doe 23 asp.net asp.net-mvc

我正在使用ASP.NET身份登录的应用程序中的注销功能.我可以成功登录但是当我退出然后尝试再次登录时,我收到以下消息:

The provided anti-forgery token was meant for a different claims-based user than the current user.
Run Code Online (Sandbox Code Playgroud)

这是我的注销代码:

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

**SignInManager.cs**
 public void Logout()
        {
            AuthenticationManager.SignOut(); 
        }
Run Code Online (Sandbox Code Playgroud)

用户按下注销按钮后,他将进入登录屏幕.网址仍然显示" http:// localhost:8544/Login/Logout ".因为我们在登录屏幕上,所以它应该只是说" http:// localhost:8544/Login ".

blo*_*art 12

你回来了View,而不是打电话RedirectToAction().所以发生的事情是视图在注销请求的上下文中运行,用户仍然登录.在请求完成之前,它们不会被注销.

所以,试试吧

public ActionResult Logout()
{
    SignInManager.Logout();
    return RedirectToAction("Index", "Home");
}
Run Code Online (Sandbox Code Playgroud)

  • 我有相同的问题.使用openidconnect和基于令牌的身份验证.默认情况下,在cookie中存储xsref标记.我已经看到令牌被传递回api post请求,但是失败了400错误说(提供的防伪令牌是针对与当前用户不同的基于声明的用户).尝试用AutoValidateAntiforgeryToken替换ValidateAntiforgeryToken.还尝试切换app.UseAuthentication()的顺序; 和app.UseXsrf();,但没有问题.我被卡住了,不知道哪个声称错误在谈论. (2认同)

小智 10

对我有用的是切换所使用的中间件的顺序.首先添加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);
});
Run Code Online (Sandbox Code Playgroud)

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


Jus*_*tin 8

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

  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");
   }
}
Run Code Online (Sandbox Code Playgroud)
  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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我在视图中反复调用它以在已经登录时将所有打开的登录表单重定向到登录页面之外:

<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>
Run Code Online (Sandbox Code Playgroud)

这对我来说效果很好。希望对你有帮助。


uni*_*niv 7

尝试这个:

public ActionResult Logout()
{
    AuthenticationManager.SignOut();
    Session.Abandon();
    return RedirectToAction("Index");
}
Run Code Online (Sandbox Code Playgroud)

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

  • asp.net auth没有以任何方式链接到会话:) (5认同)
  • @blowdart 是的,但根据应用程序,清除会话变量可能是有意义的,特别是如果与该用户的会话相关联,同时用户已注销。 (3认同)

Sea*_*ean 5

我很长一段时间以来一直在登录时遇到同样的错误,但无法弄清原因。最终我找到了它,所以我把它发布在这里(尽管这是稍有不同的原因),以防其他人拥有它。

这是我的代码:

//
// 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...
Run Code Online (Sandbox Code Playgroud)

这对于99.99%的登录来说效果很好,但是直到现在,直到现在我仍然遇到上述错误,尽管我无法重现。

仅当有人快速连续两次单击登录按钮时,才会发生该错误。但是,如果我删除该AuthenticationManager.SignOut行中的行Login,那很好。我不确定为什么要将那条线放在那里,但这会导致问题-删除它可以解决问题。