เบราว์เซอร์จะไม่ตั้งค่าคุกกี้ ASP.NET_SessionId ตามคำขอการโพสต์ของเกตเวย์การชำระเงินในเว็บไซต์ของเรา


12

เราประสบปัญหาแปลก ๆ กับกระบวนการชำระเงินของเว็บแอปพลิเคชันซึ่งทำให้ข้อมูลเซสชันสูญหาย

ในขั้นตอนนี้หลังจากที่ผู้ใช้หน้าเช็คเอาต์ของเราถูกเปลี่ยนเส้นทางไปยังหน้าของผู้ให้บริการชำระเงินและเปลี่ยนเส้นทางกลับไปที่เว็บไซต์ของเรา (ไปยัง URL ที่เราระบุไว้) ทันทีที่ทำเสร็จ การเปลี่ยนเส้นทางครั้งสุดท้ายนี้กระทำโดยการประเมินโค้ด HTML ของเบราว์เซอร์ของผู้ให้บริการชำระเงินซึ่งโดยทั่วไปจะประกอบด้วยแบบฟอร์มที่โพสต์ไปยังเว็บไซต์ของเราและโค้ดจาวาสคริปต์สองสามบรรทัดที่โพสต์แบบฟอร์มนั้น ณ จุดนี้เบราว์เซอร์ทำให้คำขอโพสต์ แต่ไม่ได้ตั้งค่าคุกกี้ "ASP.NET_SessionId" ซึ่งมีอยู่ในคำขอก่อนหน้านี้ที่ทำกับโดเมนเดียวกันทั้งหมด (โดเมนแอปพลิเคชันของเรา) สิ่งที่แปลกกว่าคือมันตั้งค่าคุกกี้อื่นที่เราใช้ชื่อว่า "AcceptCookie" เพียงเลือกที่จะวางคุกกี้ "ASP.NET_SessionId"

เพื่อแสดงให้เห็นถึงสถานการณ์ที่ฉันถ่ายภาพหน้าจอบางส่วน (ในภาพหน้าจอสี่เหลี่ยมสีส้มและสีเขียวมีค่าเดียวกันทั้งหมด)

  1. นี่คือคำขอที่เกิดขึ้น (กับแอปพลิเคชันของเรา) เมื่อผู้ใช้กดปุ่ม "ชำระเงิน" หลังจากคำขอนี้ผู้ใช้ถูกเปลี่ยนเส้นทางไปยังหน้าของผู้ให้บริการชำระเงิน

คำขอเช็คเอาท์

  1. นี่คือหน้าสุดท้ายที่ให้บริการโดยผู้ให้บริการชำระเงินหลังจากผู้ใช้เสร็จสิ้นแล้ว อย่างที่คุณเห็นมันเป็นเพียงรูปแบบง่าย ๆ ที่โพสต์โดยอัตโนมัติไปยังโดเมนของเราเมื่อโหลดหน้าเว็บ

คำตอบสุดท้ายของผู้ให้บริการชำระเงิน

  1. แต่คำขอโพสต์นี้ไม่รวมคุกกี้ "ASP.NET_SessionId" ซึ่งส่งผลให้ได้รับรหัสเซสชันใหม่และการสูญเสียข้อมูลเซสชันก่อนหน้า และอีกครั้งเพียงแค่ "ASP.NET_SessionId" หายไปไม่ใช่อีกคนหนึ่งชื่อ "AcceptCookie"

คำขอโพสต์ที่นำผู้ใช้กลับสู่เว็บไซต์ของเรา (สร้างด้วย javascript ในขั้นตอนก่อนหน้า)

ในที่สุดเราก็พบว่าในเบราว์เซอร์เวอร์ชันเก่าปัญหานี้จะไม่เกิดขึ้น ใน Firefox 52 มันใช้งานได้อย่างมีเสน่ห์ แต่ใน Firefox 71 ปัญหาดังกล่าวข้างต้นเกิดขึ้น

ความคิดใด ๆ

หมายเหตุ: เป็นแอปพลิเคชัน ASP.NET MVC ที่มี targetFramework = "4.5.2"

ขอให้มีความสุขมาก ๆ ในวันนี้นะ

คำตอบ:


16

เราคิดออก

อย่างใดอย่างหนึ่ง "ASP.NET_SessionId" แอตทริบิวต์ของคุกกี้ "SameSite" เริ่มต้นที่ "หละหลวม" และสิ่งนี้ทำให้คุกกี้เซสชั่นไม่ได้ถูกเพิ่มลงในคำขอที่ทำโดยรหัสจาวาสคริปต์ของเกตเวย์การชำระเงิน

เราได้เพิ่มกฎต่อไปนี้ลงในไฟล์ 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 = "ไม่มี" แอตทริบิวต์ไปยังโหนด sessionState ในไฟล์ web.config

<sessionState cookieSameSite="None" />

โปรดใช้ความระมัดระวังกับการเปลี่ยนแปลงการกำหนดค่านี้เนื่องจากรุ่นกรอบงาน. net รุ่นเก่าไม่รองรับและทำให้เว็บไซต์ของคุณแสดงหน้าข้อผิดพลาด

โดยวิธีที่เรายังคงมีปัญหากับเบราว์เซอร์ใน IOS 12 แต่ฉันคิดว่ามันเกี่ยวข้องกับข้อผิดพลาดที่ยืนยันนี้

ปรับปรุง 2 : ดูคำตอบของเซมินสำหรับการแก้ไขที่เป็นไปได้เกี่ยวกับปัญหา IOS

อัปเดต 3 : โดยการรวมสิ่งที่ค้นพบกับคำแนะนำในคำตอบของเซมินเราได้ทำตามกฎการเขียนซ้ำต่อไปนี้ เราใช้การกำหนดค่านี้ในการผลิต แต่ระวัง: มันจะทำเครื่องหมายคุกกี้ทั้งหมดด้วยแอตทริบิวต์ "SameSite: None" สำหรับเบราว์เซอร์ที่เข้ากันได้และไม่รวมแอตทริบิวต์ SameSite หากมีอยู่สำหรับเบราว์เซอร์ที่เข้ากันไม่ได้ มันอาจดูซับซ้อน แต่ฉันพยายามอธิบายผ่านบรรทัดความคิดเห็น

นี่คือการกำหนดค่า FINAL ที่เราใช้ในการผลิต:

<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 ให้คุกกี้ ASP.NET_SessionId กับ LAX กับ NONE ฉันไม่แน่ใจว่าทำไมมันถึงเกิดขึ้น ฉันหมายความว่ามันควรจะเป็น LAX ตลอดเวลา แต่เมื่อฉันยังเข้าสู่ระบบในเว็บไซต์ฉันจะได้รับไม่มี
Duke

โอ้! ฉันคลั่งไคล้เรื่องนี้มาสองวันแล้ว ในที่สุดคำตอบของคุณช่วยชีวิตฉันและความหงุดหงิด ขอบคุณ
Hemanth

1
เราพบปัญหานี้เกิดขึ้นใน Server 2016 หลังจากใช้การอัปเดตเดือนธันวาคม (KB4530689) ขอบคุณมากสำหรับการหาทางออก!
0474975

นี่เป็นเฉพาะสำหรับ dotnet core เท่านั้นหรือ ในแอปพลิเคชัน Framework ของฉันฉันแสดงตัวเลือกของคุณเป็นค่าที่ไม่ถูกต้อง
IronSean

3

ฉันแก้ไขตามคำตอบ SO หลายข้อเพื่อให้เกิดการเขียน URL นี้ใหม่ซึ่งเพิ่มSameSite=Noneลงในเซสชันคุกกี้และลบออกSameSite=Noneจากคุกกี้ทั้งหมดสำหรับเบราว์เซอร์ที่เข้ากันไม่ได้ส่วนใหญ่ จุดประสงค์ของการเขียนซ้ำนี้คือการรักษาพฤติกรรม "ดั้งเดิม" ไว้ก่อน 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 ส่วนใหญ่แม้ว่าเฟรมเวิร์กรุ่นใหม่จะมีตัวเลือกรหัสและการกำหนดค่าที่เหมาะสมเพื่อให้คุณสามารถควบคุมพฤติกรรมนี้ได้ ฉันขอแนะนำให้ทำการวิจัยตัวเลือกทั้งหมดที่มีให้คุณก่อนที่จะใช้การเขียนใหม่ของฉันข้างต้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.