我得到一个Runtime error
相关的防伪属性。
执行以下步骤:
错误: The provided anti-forgery token was meant for a different claims-based user than the current user.
可以采取哪些措施来防止此错误发生?
答案 0 :(得分:32)
我刚才遇到了同样的问题,并通过禁用登录视图的缓存来解决它。它实际上很有意义,并且不需要代码或异常处理。
我的登录控制器方法现在看起来像这样:
[AllowAnonymous]
[OutputCache(NoStore = true, Location = OutputCacheLocation.None)]
public ActionResult LogOn(Uri returnUrl)
当禁用缓存并且用户单击浏览器上的后退按钮时,会向服务器发出新请求,并再次传递页面,并将防伪签名设置为正确的用户。
我认为这是解决问题的一种更清洁,更简单和合理的方法。
答案 1 :(得分:23)
这是忽略错误并将用户返回登录屏幕的一种方法。这只是一个例子。
创建一个名为HandleAntiforgeryTokenErrorAttribute
的新类,该类继承自HandleErrorAttribute
。覆盖OnException
方法。
public class HandleAntiforgeryTokenErrorAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
filterContext.ExceptionHandled = true;
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(new { action = "Login", controller = "Account" }));
}
}
转到FilterConfig
班级并将该属性注册为全局过滤器。
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new HandleAntiforgeryTokenErrorAttribute()
{ ExceptionType = typeof(HttpAntiForgeryException) }
);
}
}
答案 2 :(得分:3)
接受的答案只捕获所有异常,因为它不像原始HandleErrorAttribute那样通过异常类型过滤它们。
使用以下代码仅处理HttpAntiForgeryException:
public static class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new HandleAntiforgeryTokenErrorAttribute());
}
}
public class HandleAntiforgeryTokenErrorAttribute : HandleErrorAttribute
{
public HandleAntiforgeryTokenErrorAttribute()
{
ExceptionType = typeof(HttpAntiForgeryException);
}
public override void OnException(ExceptionContext filterContext)
{
if (!ExceptionType.IsInstanceOfType(filterContext.Exception))
{
return;
}
filterContext.ExceptionHandled = true;
filterContext.Result =
new RedirectToRouteResult(
new RouteValueDictionary(
new {
area = string.Empty,
action = "Index",
controller = "Home"
}));
}
}
答案 3 :(得分:0)
缓存的旧页面,通过后退按钮恢复生机,包含旧的防伪标记并导致异常。 Rowan Freeman的全局过滤器解决方案重定向到登录页面。但是,此缓存问题还会导致站点使用旧令牌提供旧登录页面。提交表单将导致相同的异常。 Ergo,IMO,两种解决方案(Rowan Freeman和julealgon)都应该实施。
理论上,避免每个页面的缓存也应该起到作用,但成本很高(延迟,带宽)。我选择重新路由到登录,以便能够使用缓存并避免在登录时缓存以缓解异常,即实现两者。