【问题标题】:When attempt logoff, The provided anti-forgery token was meant for user "XXXX", but the current user is ""尝试注销时,提供的防伪令牌用于用户“XXXX”,但当前用户是“”
【发布时间】:2013-04-30 20:54:20
【问题描述】:

我有一个 MVC 4 应用程序,当表单会话到期然后用户尝试注销时遇到问题。

例如。 超时设置为 5 分钟。 用户登录。 用户在 10 分钟内什么都不做。 用户单击注销链接。 用户收到错误:“提供的防伪令牌用于用户“XXXX”,但当前用户是“”。”

然后用户必须通过一些体操来解决这个问题,以便他们可以重新登录然后重新注销(注销用于关闭他们当天的考勤卡)。

我想我明白为什么会发生这种情况......但不知道如何解决它。

编辑: 为什么我认为会发生这种情况是因为最初在加载页面时,会为当前登录的用户生成 AntiForgery 令牌。但是当会话到期并且他们尝试导航到注销页面时,当前用户是“”而不是实际用户。因此存在不匹配并呈现错误。

【问题讨论】:

  • 你能分享你的假设为什么会发生错误吗?
  • related post 看起来值得考虑。
  • 为什么您的注销操作需要防伪令牌?好像不应该。
  • 您描述的行为(以及通过它所需的“体操”)是 IMO 正确的。如果您的注销页面为之前登录的用户执行了一项操作,那么您最好确定您正在为正确的用户执行该操作...
  • 我假设您的注销进行了后期操作?如果是get的话就不会出现这个问题了,但是建议做个post注销。

标签: c# asp.net-mvc


【解决方案1】:

其实你可以用IExceptionFilter处理它,它会重定向到/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() 
{
}

您也可以使用[HandleError(ExceptionType=typeof(HttpAntiForgeryException)...],但它需要开启 customErrors。

【讨论】:

  • 我不敢相信这还没有被标记为答案。这个答案令人难以置信。
  • 对于它的价值,这对我不起作用。当我注销时,应用程序会出现同样的错误。但是,异常类型是 InvalidOperationException 而不是 HttpAntiforgeryException。这是非常通用的,简单地处理它很危险:/
  • 我尝试了这里建议的几乎所有内容:stackoverflow.com/questions/14970102/… 但这篇文章终于成功了
  • @Sinaesthetic 你确定吗?我对此进行了测试,没有任何强制转换的异常类型清楚地显示了 System.Web.Mvc.HttpAntiforgeryException
  • 我遇到了同样的问题,但在登录时。登录时如何处理?
【解决方案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";
        }
    }
});

【讨论】:

    猜你喜欢
    • 2016-03-19
    • 2015-02-01
    • 2013-12-18
    • 2015-01-14
    • 2013-02-04
    • 2018-01-12
    • 2013-10-06
    • 2015-12-15
    • 1970-01-01
    相关资源
    最近更新 更多