浏览器不会在付款网关向我们网站的发布请求中设置ASP.NET_SessionId cookie


12

我们的Web应用程序的付款过程遇到了一个奇怪的问题,该问题导致会话数据丢失。

在此过程中,一旦我们的结帐页面用户被重定向到付款提供商的页面,并在其完成操作后立即被重定向回到我们的网站(我们指定的网址)。最后的重定向是通过浏览器对付款服务提供商的html代码的评估来完成的,该html代码基本上由发布到我们网站的表单和几行在页面加载时发布的javascript代码组成。此时,浏览器发出了发布请求,但没有设置“ ASP.NET_SessionId” cookie,该cookie出现在对完全相同的域(我们的应用程序的域)的先前请求中。更奇怪的是,它设置了另一个我们使用的名为“ AcceptCookie”的cookie。它只是选择删除“ ASP.NET_SessionId” cookie。

为了说明这种情况,我拍摄了一些屏幕截图。(在这些屏幕截图中,橙色和绿色矩形包含完全相同的值。)

  1. 这是用户按下“签出”按钮时对我们的应用程序发出的请求。请求完成后,用户将被重定向到付款提供商的页面。

退房要求

  1. 这是付款提供商在用户那里完成后所提供的最终页面。如您所见,这只是一个简单的表单,页面加载后会自动发布到我们的域中。

支付提供商的最终回应

  1. 但是此发布请求不包括“ ASP.NET_SessionId” cookie,该cookie会导致获取新的会话ID并丢失先前的会话数据。同样,仅缺少“ ASP.NET_SessionId”,而没有另一个名为“ AcceptCookie”的对象。

发布将用户带回我们网站的请求(在上一步中使用javascript制作)

最后,我们发现在较旧版本的浏览器上不会发生此问题。在Firefox 52上,它像一个超级按钮一样工作,但是在Firefox 71上,发生了上述问题。

有任何想法吗?

注意:这是带有targetFramework =“ 4.5.2”的ASP.NET MVC应用程序

祝你今天愉快。

Answers:


16

我们知道了。

不知何故,“ ASP.NET_SessionId” cookie的“ SameSite”属性默认为“ Lax”,这导致会话cookie不被添加到付款网关的javascript代码发出的请求中。

我们将以下规则添加到web.config文件中,以覆盖此值并将其设置为“ None”。

<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仍然存在问题。

因此,我们需要向web.config文件中的sessionState节点添加cookieSameSite =“ None”属性。

<sessionState cookieSameSite="None" />

但是,请注意此配置更改,因为较早的.net框架版本不支持此更改,并导致您的站点显示错误页面。

顺便说一句,我们仍然在IOS 12中遇到浏览器问题。但是我认为这与已确认的错误有关

更新2:请参阅zemien的答案以获取有关IOS问题的可能解决方法

更新3:通过将我们的发现与zemien答案中的建议相结合,我们提出了以下重写规则。我们一直在生产中使用此配置。但要注意:对于兼容的浏览器,它会将所有cookie标记为“ 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。此问题来自于12月10日发行的KB4533011(.net 4.7及更低版本)和KB4533004(.net 4.8)上最具体的KB4533097(support.microsoft.com/zh-cn/help/4533097/kb4533097
S. Pineau

我有同样的问题,但是有时asp.net mvc使用LAX给客户ASP.NET_SessionId cookie,有时使用NONE。我不确定为什么会这样。我的意思是应该一直都是LAX,但是当我在网站上登录时仍然无法获得任何信息。
杜克

天啊!我为这个问题疯狂了两天。最后,您的回答挽救了我的精力和沮丧。谢谢。
Hemanth

1
应用十二月更新后,我们在Server 2016上发生了此问题。(KB4530689)。非常感谢您找到解决方案!
user0474975

这仅适用于dotnet核心吗?在我的Framework应用程序中,我将这些选项显示为要设置的无效值。
IronSean

3

我对几个SO答案进行了修改,以提出此​​URL重写,该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>

尽管较新的Frameworks具有适当的代码和配置选项可让您控制此行为,但它对大多数ASP .Net和ASP .Net Core应用程序均适用。我建议您在使用上面的重写之前,先研究所有可用的选项。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.