RequestVerificationToken cookie не присутствует в ответе
Мое приложение ASP.NET MVC предотвращает CSRF-атаки, используя атрибут ValidateAntiForgeryToken и вызывая Html.AntiForgeryToken, чтобы записать скрытый элемент ввода со значением токена, а также поместить токен в файл cookie.
Мой журнал исключений сообщает о случаях возникновения исключения HttpAntiForgeryException, которые выглядят так, как будто они были вызваны действительными запросами (реферер выглядит правильно). Ответ, вызывающий исключение, также содержит __RequestValidationToken в поле формы со значением токена. Однако в запросе отсутствует необходимый файл cookie, что приводит к сбою проверки и выбрасыванию исключения.
Я пытаюсь понять, почему этот файл cookie отсутствует, и нашел следующие возможные причины:
- Коллекция cookie-файлов заполнена для домена. - Если бы это было здесь, я бы ожидал видеть 20/50 файлов cookie в каждом запросе (кстати, все пользовательские агенты - IE7 и IE8), и каким-то образом этот файл cookie удаляется. Я вижу от 3 до 23 файлов cookie в разных случаях, за исключением
- Предел данных куки был достигнут. - Этого не происходит. Просматривая журналы, я вижу, что коллекция файлов cookie мала.
- Ответ отправляется до того, как файл cookie может быть добавлен. - Не уверен насчет этого. Ручной вызов Reponse.Flush в голове приводит к исключению, утверждающему, что коллекция куки не может быть изменена после отправки ответа.
- ?
В отчаянии я обращаюсь к людям в 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);
}