我有一个MVC 4应用程序,并在表单会话到期时遇到问题,然后用户尝试注销。
实施例。 超时设置为5分钟。 用户登录。 用户10分钟不做任何事。 用户单击LogOff链接。 用户收到错误:“提供的防伪令牌适用于用户”XXXX“,但当前用户为”“。”
然后,用户必须通过一些体操来解决这个问题,以便他们可以重新登录然后重新注销(注销正在用于关闭当天的时间卡)。我想我明白为什么会发生这种情况......但不知道如何解决它。
编辑: 为什么我认为发生这种情况是因为最初加载页面时,会为当前登录的用户生成AntiForgery令牌。但是当会话到期并且他们尝试导航到注销页面时,当前用户是“”而不是实际用户。因此存在不匹配并且呈现错误。
答案 0 :(得分:23)
实际上您可以使用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。
答案 1 :(得分: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";
}
}
});