Браузер не установит файл cookie ASP.NET_SessionId при запросе поста платежного шлюза на наш сайт.

12

У нас возникла странная проблема с процессом оплаты нашего веб-приложения, которая приводит к потере данных сеанса.

В этом процессе, после того, как наша страница оформления заказа перенаправляется на страницу поставщика платежа и возвращается на наш сайт (по указанному нами URL-адресу), как только он / она это сделает. Последнее перенаправление выполняется путем оценки браузером HTML-кода поставщика платежа, который в основном состоит из формы, которая публикует на нашем сайте, и нескольких строк кода JavaScript, которые публикуются, которые формируются при загрузке страницы. В этот момент браузер выполняет пост-запрос, но не устанавливает cookie-файл «ASP.NET_SessionId», который присутствует в предыдущих запросах к тому же домену (домену нашего приложения). Что еще более странно, это то, что он устанавливает другой cookie, который мы используем, с именем «AcceptCookie». Он просто выбирает удаление файла «ASP.NET_SessionId».

Для иллюстрации ситуации я сделал несколько скриншотов. (На этих скриншотах оранжевые и зеленые прямоугольники содержат одинаковое значение.)

  1. Это запрос, который делается (к нашему приложению), когда пользователь нажимает кнопку «Оформить заказ». После этого запроса пользователь перенаправляется на страницу платежного оператора.

запрос на выезд

  1. Это последняя страница, которая обслуживается платежным провайдером после того, как пользователь завершил работу. Как видите, это просто простая форма, которая автоматически публикуется на нашем домене при загрузке страницы.

окончательный ответ поставщика платежа

  1. Но этот пост-запрос не включает cookie-файл «ASP.NET_SessionId», который приводит к получению нового идентификатора сеанса и потере данных предыдущего сеанса. И снова, отсутствует только «ASP.NET_SessionId», а не другой с именем «AcceptCookie».

отправить запрос, который возвращает пользователя на наш сайт (сделан с помощью javascript на предыдущем шаге)

Наконец мы поняли, что в старых версиях браузеров этой проблемы не возникает. На Firefox 52 он работает как шарм, но на Firefox 71 возникает вышеупомянутая проблема.

Любые идеи?

Примечание. Это приложение ASP.NET MVC с targetFramework = "4.5.2".

Хорошего дня.

Э. Озгюр
источник

Ответы:

16

Мы поняли это.

Каким-то образом атрибут «SameSite» cookie «ASP.NET_SessionId» по умолчанию имеет значение «Lax», и это приводит к тому, что cookie-файл сеанса не добавляется к запросу, выполненному кодом JavaScript шлюза оплаты.

Мы добавили следующее правило в файл web.config, чтобы переопределить это значение и установить для него значение «Нет».

<configuration>
  <system.webServer>
    <rewrite>
      <outboundRules>
        <rule name="Add SameSite" preCondition="No SameSite">
          <match serverVariable="RESPONSE_Set_Cookie" pattern=".*" negate="false" />
          <action type="Rewrite" value="{R:0}; SameSite=None" />
          <conditions>
          </conditions>
        </rule>
        <preConditions>
          <preCondition name="No SameSite">
            <add input="{RESPONSE_Set_Cookie}" pattern="." />
            <add input="{RESPONSE_Set_Cookie}" pattern="; SameSite=None" negate="true" />
          </preCondition>
        </preConditions>
      </outboundRules>
    </rewrite>
  </system.webServer>
</configuration>

ОБНОВЛЕНИЕ 1 : просто добавление вышеуказанной конфигурации решило проблему для современных браузеров, но мы поняли, что у нас все еще есть проблемы со старыми версиями Micosoft Edge и Internet Explorer.

Поэтому нам нужно было добавить атрибут cookieSameSite = "None" в узел sessionState в файле web.config.

<sessionState cookieSameSite="None" />

Будьте осторожны с этим изменением конфигурации, так как более старые версии .net Framework не поддерживают его и приводят к тому, что ваш сайт отображает страницу с ошибкой.

Кстати, у нас все еще есть проблемы с браузерами в IOS 12. Но я думаю, что это связано с этой подтвержденной ошибкой

ОБНОВЛЕНИЕ 2 : см. Ответ zemien для возможного решения проблемы IOS

ОБНОВЛЕНИЕ 3 : Объединив наши выводы с предложениями в ответе zemien, мы разработали следующие правила переписывания. Мы использовали эту конфигурацию в производстве. Но будьте осторожны: он помечает все файлы cookie атрибутом «SameSite: None» для совместимых браузеров и исключает атрибут SameSite, если он существует, для несовместимых браузеров. Это может показаться сложным, но я попытался объяснить это с помощью комментариев.

Это финальная конфигурация, которую мы используем в производстве:

<configuration> 

  <system.webServer>

    <rewrite>

      <outboundRules>

        <preConditions>
          <!-- Browsers incompatible with SameSite=None -->
          <preCondition name="IncompatibleWithSameSiteNone" logicalGrouping="MatchAny">
            <add input="{HTTP_USER_AGENT}" pattern="(CPU iPhone OS 12)|(iPad; CPU OS 12)" />
            <add input="{HTTP_USER_AGENT}" pattern="(Chrome/5)|(Chrome/6)" />
            <add input="{HTTP_USER_AGENT}" pattern="( OS X 10_14).*(Version/).*((Safari)|(KHTML, like Gecko)$)" />
          </preCondition>

          <!-- Rest of the browsers are assumed to be compatible with SameSite=None -->
          <preCondition name="CompatibleWithSameSiteNone" logicalGrouping="MatchAll">
            <add input="{HTTP_USER_AGENT}" pattern="(CPU iPhone OS 12)|(iPad; CPU OS 12)" negate="true" />
            <add input="{HTTP_USER_AGENT}" pattern="(Chrome/5)|(Chrome/6)" negate="true" />
            <add input="{HTTP_USER_AGENT}" pattern="( OS X 10_14).*(Version/).*((Safari)|(KHTML, like Gecko)$)" negate="true" />
          </preCondition>

        </preConditions>

        <!-- Rule 1: Remove SameSite part from cookie for incompatible browsers if exists -->
        <rule name="Remove_SameSiteCookie_IfExists_ForLegacyBrowsers" preCondition="IncompatibleWithSameSiteNone">
          <match serverVariable="RESPONSE_Set-Cookie" pattern="(.*)(SameSite=.*)" />
          <action type="Rewrite" value="{R:1}" />
        </rule>

        <!-- Rule 2: Override SameSite's value to None if exists, for compatible browsers -->
        <rule name="Override_SameSiteCookie_IfExists_ForModernBrowsers" preCondition="CompatibleWithSameSiteNone">
          <match serverVariable="RESPONSE_Set-Cookie" pattern="(.*)(SameSite=.*)" />
          <action type="Rewrite" value="{R:1}; SameSite=None" />
        </rule>

        <!-- Rule 3: Add SameSite attribute with the value None if it does not exists, for compatible browsers -->
        <rule name="Add_SameSiteCookie_IfNotExists_ForModernBrowsers" preCondition="CompatibleWithSameSiteNone">
          <match serverVariable="RESPONSE_Set-Cookie" pattern=".*"/>
          <!-- Condition explanation: Cookie data contains some string value but does not contain SameSite attribute -->
          <conditions logicalGrouping="MatchAll">
            <add input="{R:0}" pattern="^(?!\s*$).+"/>
            <add input="{R:0}" pattern="SameSite=.*" negate="true"/>
          </conditions>
          <action type="Rewrite" value="{R:0}; SameSite=None" />
        </rule>

      </outboundRules>

    </rewrite>    

  </system.webServer>  

</configuration>
Э. Озгюр
источник
Спасибо @ EÖzgür. Эта проблема возникла из KB4533097 ( support.microsoft.com/en-us/help/4533097/kb4533097 ) для наиболее конкретно KB4533011 (.net 4.7 и ниже) и KB4533004 (.net 4.8), выпущенных 10 декабря.
S. Pineau
У меня та же проблема, но иногда asp.net mvc дает клиенту файлы cookie ASP.NET_SessionId с LAX, иногда с NONE. Я не уверен, почему это происходит. Я имею в виду, что это должно быть LAX все время, но все же, когда я захожу на сайт, я могу получить NONE.
Герцог
О чувак! Я был без ума от этой проблемы в течение двух дней. Наконец твой ответ спас мой день и разочарование. Спасибо.
Гиман
1
Эта проблема возникла на сервере 2016 после применения декабрьских обновлений. (KB4530689). Большое спасибо за поиск решения!
user0474975
Это только для дотнет ядра? В моем приложении Framework я показываю эти параметры в качестве недопустимых значений.
IronSean
3

Я изменил несколько ответов SO, чтобы придумать переписывание URL-адреса, которое добавляет SameSite=Noneфайлы cookie сеанса, а также удалить SameSite=Noneиз всех файлов cookie для большинства несовместимых браузеров. Целью этого переписывания является сохранение «устаревшего» поведения до Chrome 80.

Полная информация в моем блоге Coder Frontline :

<rewrite>
  <outboundRules>
    <preConditions>
      <!-- Checks User Agent to identify browsers incompatible with SameSite=None -->
      <preCondition name="IncompatibleWithSameSiteNone" logicalGrouping="MatchAny">
        <add input="{HTTP_USER_AGENT}" pattern="(CPU iPhone OS 12)|(iPad; CPU OS 12)" />
        <add input="{HTTP_USER_AGENT}" pattern="(Chrome/5)|(Chrome/6)" />
        <add input="{HTTP_USER_AGENT}" pattern="( OS X 10_14).*(Version/).*((Safari)|(KHTML, like Gecko)$)" />
      </preCondition>
    </preConditions>

    <!-- Adds or changes SameSite to None for the session cookie -->
    <!-- Note that secure header is also required by Chrome and should not be added here -->
    <rule name="SessionCookieAddNoneHeader">
      <match serverVariable="RESPONSE_Set-Cookie" pattern="((.*)(ASP.NET_SessionId)(=.*))(SameSite=.*)?" />
      <action type="Rewrite" value="{R:1}; SameSite=None" />
    </rule>

    <!-- Removes SameSite=None header from all cookies, for most incompatible browsers -->
    <rule name="CookieRemoveSameSiteNone" preCondition="IncompatibleWithSameSiteNone">
      <match serverVariable="RESPONSE_Set-Cookie" pattern="(.*)(SameSite=None)" />
      <action type="Rewrite" value="{R:1}" />
    </rule>
  </outboundRules>
</rewrite>

Это должно работать для большинства приложений ASP .Net и ASP .Net Core, хотя более новые Frameworks имеют надлежащие параметры кода и конфигурации, позволяющие контролировать это поведение. Я бы порекомендовал изучить все варианты, доступные вам, прежде чем использовать мой переписать выше.

zemien
источник