5

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

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

空的 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");
}

[编辑:简化代码示例]

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

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

任何意见,将不胜感激!

干杯,戴夫

4

3 回答 3

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();
    }

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

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

于 2010-10-27T09:41:03.227 回答
0

您可以使用相同的盐:

<% 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");
}

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

于 2010-10-27T09:25:40.017 回答
-2

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

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

于 2013-09-03T16:26:49.817 回答