RequestVerificationToken cookie не присутствует в ответе

Мое приложение ASP.NET MVC предотвращает CSRF-атаки, используя атрибут ValidateAntiForgeryToken и вызывая Html.AntiForgeryToken, чтобы записать скрытый элемент ввода со значением токена, а также поместить токен в файл cookie.

Мой журнал исключений сообщает о случаях возникновения исключения HttpAntiForgeryException, которые выглядят так, как будто они были вызваны действительными запросами (реферер выглядит правильно). Ответ, вызывающий исключение, также содержит __RequestValidationToken в поле формы со значением токена. Однако в запросе отсутствует необходимый файл cookie, что приводит к сбою проверки и выбрасыванию исключения.

Я пытаюсь понять, почему этот файл cookie отсутствует, и нашел следующие возможные причины:

  1. Коллекция cookie-файлов заполнена для домена. - Если бы это было здесь, я бы ожидал видеть 20/50 файлов cookie в каждом запросе (кстати, все пользовательские агенты - IE7 и IE8), и каким-то образом этот файл cookie удаляется. Я вижу от 3 до 23 файлов cookie в разных случаях, за исключением
  2. Предел данных куки был достигнут. - Этого не происходит. Просматривая журналы, я вижу, что коллекция файлов cookie мала.
  3. Ответ отправляется до того, как файл cookie может быть добавлен. - Не уверен насчет этого. Ручной вызов Reponse.Flush в голове приводит к исключению, утверждающему, что коллекция куки не может быть изменена после отправки ответа.
  4. ?

В отчаянии я обращаюсь к людям в SO и спрашиваю о любых других возможных причинах этого пропавшего cookie, которые я могу расследовать.

2 ответа

У меня была точно такая же проблема. Мой контент был представлен через междоменный iframe. По словам Адама Янга, IE будет автоматически блокировать сторонние куки, если вы не определите политику P3P в заголовке.

Я добавил код для добавления политики p3p в заголовок и просто вызывал его из каждого действия, которое я использую в своем iframe. До сих пор мы не видели, чтобы эта ошибка появлялась. Я надеюсь, что это решение поможет кому-то еще.

public static void SetP3PCompactPolicy()
{
    HttpContext.Current.Response.AddHeader("p3p", 
    "CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"");
}

Я также определил машинный ключ, хотя я не уверен, что это было необходимо.

Согласно ответу Джоша (проблема между доменами в iFrame), я поместил часть кода в метод BeginExecute моего контроллера, чтобы добиться желаемого поведения для каждого вызова. В дополнение к базовому контроллеру, на котором основан любой другой контроллер, вы можете добиться того, что все ваши действия будут выполняться, если ваш сайт встроен в iFrame.

protected override IAsyncResult BeginExecute(System.Web.Routing.RequestContext requestContext, AsyncCallback callback, object state)
{
    requestContext.HttpContext.Response.AddHeader("p3p", "CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"");

    return base.BeginExecute(requestContext, callback, state);
}
Другие вопросы по тегам