C# MVC4应用中正确处理HttpAntiforyException的一种方法
以下是场景: 我有一个登录页面,当用户签名时,它被重定向到主应用程序页面。然后用户使用浏览器返回按钮,现在他进入登录页面。他尝试再次登录,但现在引发异常: HttpAntiforyException(0x80004005):提供的防伪令牌是针对用户“”的,但当前用户是“用户名” 我知道这与缓存有关。我使用自定义NoCache筛选器禁用了登录操作的浏览器缓存,该筛选器设置了所有必需的标题-无缓存、无存储、必须重新验证等,但C# MVC4应用中正确处理HttpAntiforyException的一种方法,c#,asp.net-mvc,antiforgerytoken,C#,Asp.net Mvc,Antiforgerytoken,以下是场景: 我有一个登录页面,当用户签名时,它被重定向到主应用程序页面。然后用户使用浏览器返回按钮,现在他进入登录页面。他尝试再次登录,但现在引发异常: HttpAntiforyException(0x80004005):提供的防伪令牌是针对用户“”的,但当前用户是“用户名” 我知道这与缓存有关。我使用自定义NoCache筛选器禁用了登录操作的浏览器缓存,该筛选器设置了所有必需的标题-无缓存、无存储、必须重新验证等,但 这在所有浏览器上都不起作用 尤其是Safari(大多数情况下是移动的)完
- 这在所有浏览器上都不起作用
- 尤其是Safari(大多数情况下是移动的)完全忽略了这些设置
- 在不向用户显示存在任何问题的情况下处理异常(对用户完全透明)
- 通过替换防伪令牌用户名来防止此问题,如果我的浏览器缓存相关攻击在下一版本的浏览器中停止工作,该用户名将允许用户再次登录,而不会出现此异常李>
- 我真的不想依赖于浏览器行为,因为每个浏览器的行为都不同
我已经添加了以下对我有效的解决方案。您应该能够通过添加操作筛选器来处理错误来处理异常
[HandleError(View="AntiForgeryExceptionView", ExceptionType = typeof(HttpAntiForgeryException))]
Todo所以请确保在web.config中打开自定义错误
<customErrors mode="On"/>
您还可以查看此文件以了解有关句柄错误的更多信息
编辑既然您使用的是MVC4,而博客是关于MVC3的,您也可以查看一下,但版本应该不会有什么不同。经过一段时间的调查,我想我找到了一些方法,可以为用户消除这个错误。它并不完美,但至少不显示错误页面: 我根据
HandleErrorAttribute
创建了过滤器:
[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes",
Justification = "This attribute is AllowMultiple = true and users might want to override behavior.")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class LoginAntiforgeryHandleErrorAttribute : FilterAttribute, IExceptionFilter
{
#region Implemented Interfaces
#region IExceptionFilter
/// <summary>
/// </summary>
/// <param name="filterContext">
/// The filter context.
/// </param>
/// <exception cref="ArgumentNullException">
/// </exception>
public virtual void OnException(ExceptionContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (filterContext.IsChildAction)
{
return;
}
// If custom errors are disabled, we need to let the normal ASP.NET exception handler
// execute so that the user can see useful debugging information.
if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
{
return;
}
Exception exception = filterContext.Exception;
// If this is not an HTTP 500 (for example, if somebody throws an HTTP 404 from an action method),
// ignore it.
if (new HttpException(null, exception).GetHttpCode() != 500)
{
return;
}
// check if antiforgery
if (!(exception is HttpAntiForgeryException))
{
return;
}
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary
{
{ "action", "Index" },
{ "controller", "Home" }
});
filterContext.ExceptionHandled = true;
}
#endregion
#endregion
}
该解决方案的主要思想是将防伪异常重定向到主索引操作。如果用户仍然未经身份验证,则会显示登录页面;如果用户已通过身份验证,则会显示索引页面
更新1
这个解决方案有一个潜在的问题。如果有人使用不同的凭据登录,则在出现错误时应添加额外的登录运行时-注销以前的用户并登录新用户。这种情况不会得到处理。如果您只有一个或几个受影响的函数,那么创建一个过滤器在技术上可能有点过火。一个更简单但非通用的解决方案是简单地删除特定方法的
[ValidateAntiForgeryToken]
,并在检查用户是否登录后添加手动验证
if (User.Identity.IsAuthenticated)
{
return RedirectToAction("Index", "Home");
}
System.Web.Helpers.AntiForgery.Validate();
/* proceed with authentication here */
一个老问题-但我今天遇到了这个问题,我解决这个问题的方法是重定向到注销操作,如下所示:
public ActionResult Login(string returnUrl)
{
if (WebSecurity.IsAuthenticated)
return RedirectToAction("LogOff");
...
}
是的,但这说明了重定向(因此处理此错误会中断当前操作(执行)。我希望在不中断操作的情况下处理此错误,因此在本例中,处理、替换用户名并使用正确的数据继续登录。我认为,当您捕获到错误时,可以将其重定向到视图(控制器)在这里,您可以用以前输入的数据替换用户名并继续登录。另请参见:这对我来说非常有效。我不需要它来做任何幻想。只是不要抛出黄色屏幕。谢谢,这似乎非常有效,并且仍然提供相同的安全性。这对我不起作用,它会给出完全相同的错误,但在这一行:System.Web.Helpers.antifforgery.Validate();@AmrElgarhy没错,现在你可以抓住它了!
public ActionResult Login(string returnUrl)
{
if (WebSecurity.IsAuthenticated)
return RedirectToAction("LogOff");
...
}