Проблема с несколькими вкладками MVC ValidateAntiForgeryToken

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

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

Пустой проект MVC 2: одна страница просмотра, один контроллер

Вид:

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

Контроллер:

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

[EDIT: упрощенный пример кода]

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

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

Любые советы будут оценены!

Cheers, Dave

3 ответа

Настоящим ответом на эту проблему является просто то, что вы не должны использовать токен анти-подделки в формах регистрации!

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


Посмотрев исходный код 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();
 }

Поскольку на вашей другой вкладке, которую вы сейчас подписали в приведенном выше коде, аннулируется существующий токен, который не содержит имя пользователя .Identity.Name.

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


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

<% using(Html.BeginForm("SignIn", "Home", FormMethod.Post)) {%>
 <%= Html.AntiForgeryToken("123")%>
 
<%}%>
<% using(Html.BeginForm("Protected", "Home", FormMethod.Post)) {%>
 <%= Html.AntiForgeryToken("456")%>
 
<%}%>

И в вашем контроллере:

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

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

licensed under cc by-sa 3.0 with attribution.