MVC ValidateAntiForgeryToken проблема с несколькими вкладками - PullRequest
5 голосов
/ 27 октября 2010

Мы получили «Требуемый токен против подделки не был предоставлен или был недействительным». ошибок, и в некоторых дальнейших исследованиях мне удалось воссоздать проблему в ее простейшей форме - я либо делаю что-то совершенно неправильно, либо это ограничение системы токенов против подделки.

В любом случае, я буду признателен за совет!

Пустой проект 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");
}

[РЕДАКТИРОВАТЬ: упрощенный пример кода]

Чтобы воссоздать исключение, откройте две не вошедшие вкладки - войдите на первой вкладке, а затем войдите на второй вкладке.

Вторая вкладка всегда будет генерировать исключение для защиты от подделки, когда я предполагаю, что правильным поведением будет перенаправление на страницу входа (совместное использование сеанса / аутентификация исходной вкладки входа)

Буду признателен за любой совет!

Cheers, Dave

Ответы [ 3 ]

5 голосов
/ 27 октября 2010

Глядя на исходный код MVC 2, кажется, что скрытое поле AntiForgeryToken включает в себя сериализованный User.Identity.Name, если вы вошли в систему. В строке 69 ValidateAntiForgeryTokenAttribute кажется, что он проверяет ваш токен с текущим пользователем.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.

Thisможно исправить, добавив !string.IsNullOrEmpty(formToken.Username) вокруг этой проверки, но я не знаю, вызовет ли это проблемы с безопасностью, плюс это означает наличие собственной сборки MVC 2.

0 голосов
/ 03 сентября 2013

Реальный ответ на эту проблему заключается в том, что вы не должны использовать токен против подделки в формах входа в систему!

Бессмысленно «подделывать» пользователя в форме входа - они не авторизованы!

0 голосов
/ 27 октября 2010

Вы можете использовать ту же соль:

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

Сделайте то же самое с другим токеном, но убедитесь, что выбрали другую соль.

...