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


12

У нас виникає дивна проблема з процесом оплати нашої веб-програми, що призводить до втрати даних про сеанси.

У цьому процесі після того, як наша сторінка виїзду, користувач перенаправляється на сторінку постачальника платежів і перенаправляється назад на наш сайт (до вказаного вами URL-адреси), як тільки він / там він зробив. Останнє переадресація проводиться шляхом оцінки браузером html-коду постачальника платежів, який, в основному, складається з форми, що публікує наш веб-сайт, та декількох рядків коду javascript, які розміщуються під час завантаження сторінки. У цей момент браузер робить поштовий запит, але не встановлює cookie "ASP.NET_SessionId", який присутній у попередніх запитах, точно в тому ж домені (домен нашої програми). Що ще дивніше, що він встановлює інший файл cookie, який ми використовуємо під назвою "AcceptCookie". Він просто вибирає файл "ASP.NET_SessionId".

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

  1. Це запит, який було зроблено (до нашої програми), коли користувач натискає кнопку "Check Out". Після цього запиту користувач перенаправляється на сторінку провайдера платежів.

запит на виїзд

  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 рамки не підтримують її, і ваш сайт відображає сторінку помилок.

До речі, у нас все ще виникають проблеми з браузерами в 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 весь час, але все ж, коли я входжу на сайт, я можу отримати НІКОЛИ.
Герцог

О людино! Я божеволію від цього питання вже два дні. Нарешті ваша відповідь врятувала мені день і розчарування. Дякую.
Хемант

1
У нас ця проблема сталася на сервері 2016 року після застосування оновлень у грудні. (KB4530689). Велике спасибі за знайдене рішення!
користувач0474975

Це лише для ядра dotnet? У своїй програмі 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, хоча нові рамки мають належні параметри коду та конфігурації, які дозволяють вам контролювати цю поведінку. Я рекомендую вивчити всі наявні у вас варіанти, перш ніж використовувати переписаний вище.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.