MVC ValidateAntiForgeryToken多标签问题

Dav*_*ish 5 asp.net asp.net-mvc antiforgerytoken asp.net-mvc-2

我们得到了"未提供所需的防伪标记或无效".错误,并进行了一些进一步的调查,我设法以最简单的形式重现问题 - 我要么做一些完全错误的事情,要么这是对防伪令牌系统的限制.

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

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

视图:

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

控制器:

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

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

[编辑:简化代码示例]

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

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

任何意见,将不胜感激!

干杯,戴夫

Naz*_*Naz 5

查看MVC 2源代码,看起来AntiForgeryToken隐藏字段包括User.Identity.Name序列化,如果您已登录.在第69行,ValidateAntiForgeryTokenAttribute它似乎然后用当前User.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();
    }
Run Code Online (Sandbox Code Playgroud)

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

这可以通过添加一个!string.IsNullOrEmpty(formToken.Username)检查来修复,但我不知道这是否会打开安全问题加上它意味着有一个自定义MVC 2 Build.


Dav*_*ish -3

这个问题的真正答案很简单,您不应该在登录表单上使用防伪令牌!

在登录表单上“伪造”用户是毫无意义的——他们还没有登录!

  • 也许这个答案应该持保留态度,与 AppSec 上这个问题的答案进行权衡:http://security.stackexchange.com/questions/2120/when-the-use-of-a-antiforgerytoken-is -not-required-needed 这很晦涩,可能对每个人来说都不重要,但应该/不应该的答案并不简单。 (6认同)