【问题标题】:MVC ValidateAntiForgeryToken multi-tabs problemMVC ValidateAntiForgeryToken 多标签问题
【发布时间】:2011-05-01 04:54:15
【问题描述】:

我们收到“所需的防伪令牌未提供或无效”。错误,经过进一步调查,我设法以最简单的形式重现了问题 - 我要么做错了,要么这是防伪令牌系统的限制。

无论哪种方式,我都会很感激一些建议!

空的 MVC 2 项目: 一个视图页面,一个控制器

查看:

<%--Sign in form:--%>
<% using(Html.BeginForm("SignIn", "Home", FormMethod.Post)) {%>
    <%= Html.AntiForgeryToken()%>
    <input type="submit" value="Sign in" />
<%}%>

控制器:

public ActionResult Index()
{
    ViewData["status"] = "Index";
    return View();
}

[ValidateAntiForgeryToken]
public ActionResult SignIn()
{
    ViewData["status"] = "Signed In!";
    FormsAuthentication.SetAuthCookie("username", false);
    return View("Index");
}

[编辑:简化代码示例]

要重新创建异常,请打开两个未登录的选项卡 - 在第一个选项卡上登录,然后在第二个选项卡上登录。

当我猜测正确的行为是重定向到登录页面(共享原始登录选项卡的会话/身份验证)时,第二个选项卡将始终引发防伪异常

任何建议将不胜感激!

干杯, 戴夫

【问题讨论】:

  • 我最终解决了这个问题,完全删除了防伪令牌。如果您考虑一下,无论如何将它放在您网站的登录部分并没有任何帮助 - 因为攻击者必须知道您的用户名和密码!

标签: asp.net asp.net-mvc asp.net-mvc-2 antiforgerytoken


【解决方案1】:

您可以使用相同的盐:

<% using(Html.BeginForm("SignIn", "Home", FormMethod.Post)) {%>
    <%= Html.AntiForgeryToken("123")%>
    <input type="submit" value="Sign in" />
<%}%>

<% using(Html.BeginForm("Protected", "Home", FormMethod.Post)) {%>
    <%= Html.AntiForgeryToken("456")%>
    <input type="submit" value="Do secret stuff" />
<%}%>

在你的控制器中:

[ValidateAntiForgeryToken(Salt = "123")]
public ActionResult SignIn()
{
    ViewData["status"] = "Signed In!";
    FormsAuthentication.SetAuthCookie("username", false);
    return View("Index");
}

[Authorize]
[ValidateAntiForgeryToken(Salt = "456")]
public ActionResult Protected()
{
    ViewData["status"] = "Authed";
    return View("Index");
}

对另一个令牌执行相同的操作,但请确保选择不同的盐。

【讨论】:

  • 感谢您的回复 - 但这并不能解决问题,干杯,戴夫。
  • 它为我解决了这个问题。确保在控制器和视图中为登录表单和操作使用相同的盐,为受保护的操作和视图使用不同的盐。另外不要忘记重新编译并关闭浏览器窗口以清除所有过时的 cookie。
  • 确保关闭浏览器以开始新会话 - 实际上,您根本不需要第二个表单/控制器操作来重新创建此问题。
  • 在您最初的问题中,您谈到了不同的浏览器选项卡。如果我关闭浏览器并启动一个新浏览器,则完全没有问题。
  • 不 - 我的意思是,打开一个新的浏览器 - 然后打开两个标签。在标签 1 上登录,然后标签 2 将始终失败并出现异常。
【解决方案2】:

查看 MVC 2 源代码,如果您已登录,则 AntiForgeryToken 隐藏字段似乎包含序列化的 User.Identity.Name。在ValidateAntiForgeryTokenAttribute 的第 69 行中,似乎随后会使用当前用户检查您的令牌.Identity.Name。

    string currentUsername = AntiForgeryData.GetUsername(filterContext.HttpContext.User);
    if (!String.Equals(formToken.Username, currentUsername, StringComparison.OrdinalIgnoreCase)) {
        // error: form token is not valid for this user
        // (don't care about cookie token)
        throw CreateValidationException();
    }

因为您现在在其他选项卡中登录,所以上面的代码使不包含 User.Identity.Name 的现有令牌无效。

可以通过在该检查周围添加!string.IsNullOrEmpty(formToken.Username) 来解决此问题,但我不知道这是否会引发安全问题,而且这意味着需要自定义 MVC 2 构建。

【讨论】:

【解决方案3】:

这个问题的真正答案就是你不应该在登录表单上使用防伪令牌!

登录表单上“伪造”为用户是没有意义的 - 他们没有登录!

【讨论】:

  • 当与 AppSec 上对这个问题的答案进行权衡时,也许应该对这个答案持怀疑态度:security.stackexchange.com/questions/2120/… 这很模糊,可能对每个人都不重要,但应该/应该'不回答并不简单。
猜你喜欢
  • 1970-01-01
  • 2012-10-16
  • 1970-01-01
  • 2012-09-22
  • 1970-01-01
  • 2013-11-25
  • 1970-01-01
  • 1970-01-01
  • 2018-02-04
相关资源
最近更新 更多