问题描述
我们的Web应用程序的付款过程遇到了一个奇怪的问题,该问题导致会话数据丢失.
We're experiencing a weird problem with the payment process of our web application which results in loss of session data.
在此过程中,一旦我们的结帐页面用户被重定向到付款提供商的页面,并在其完成操作后立即被重定向回到我们的网站(我们指定的网址).最后的重定向是通过浏览器对付款提供商的html代码的评估来完成的,该html代码基本上由发布到我们网站的表单和几行在页面加载时发布的javascript代码组成.此时,浏览器发出了发布请求,但没有设置"ASP.NET_SessionId" cookie,该cookie出现在对完全相同的域(我们的应用程序的域)的先前请求中.更奇怪的是,它设置了另一个我们使用的名为"AcceptCookie"的cookie.它只是选择删除"ASP.NET_SessionId" cookie.
In this process, after our check-out page user is redirected to payment provider's page and redirected back to our site (to a url we specify) as soon as s/he's done there. This last redirect is done by browser's evaluation of the payment provider's html code which basically consists of a form that posts to our site and a few lines of javascript code that posts that form on page load. At this point browser makes the post request but does not set the "ASP.NET_SessionId" cookie which is present in the previous requests made to the exact same domain (our application's domain). What's more weird is that it sets another cookie we use named "AcceptCookie". It just simply chooses to drop "ASP.NET_SessionId" cookie.
为说明这种情况,我拍摄了一些屏幕截图.(在这些屏幕截图中,橙色和绿色矩形包含完全相同的值.)
To illustrate the situation I took some screenshots. (In these screenshots orange and green rectangles contain exactly the same value.)
- 这是当用户按下签出"按钮时向我们的应用程序发出的请求.请求完成后,用户将被重定向到付款提供商的页面.
- 这是付款服务提供商在用户那里完成后提供的最终页面.如您所见,这只是一个简单的表单,它会在页面加载时自动发布到我们的域中.
- 但是此发布请求不包含"ASP.NET_SessionId" cookie,该cookie会导致获取新的会话ID并丢失先前的会话数据.再一次,只缺少"ASP.NET_SessionId",而没有另一个名为"AcceptCookie".
发布将用户带回我们网站的请求(在上一步中使用javascript制作)
最后,我们发现在较旧版本的浏览器中不会发生此问题.在Firefox 52上,它像一个超级按钮一样工作,但是在Firefox 71上,发生了上述问题.
Finally we figured that on the older versions of browsers this problem does not occur. On Firefox 52 it works like a charm but on Firefox 71 the above problem happens.
有什么想法吗?
注意:这是一个带有targetFramework ="4.5.2"的ASP.NET MVC应用程序
Note: It's an ASP.NET MVC application with targetFramework="4.5.2"
祝你有美好的一天.
推荐答案
我们知道了.
"ASP.NET_SessionId" cookie的"SameSite"属性以某种方式默认为松驰",这导致会话cookie不会被添加到付款网关的javascript代码发出的请求中.
Somehow "ASP.NET_SessionId" cookie's "SameSite" attribute defaults to "Lax" and this causes session cookie not being added to the request that made by payment gateway's javascript code.
我们在web.config文件中添加了以下规则,以覆盖此值并将其设置为无".
We added following rule to the web.config file in order to override this value and set it to "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仍然存在问题.
UPDATE 1: Just adding above configuration solved the problem for modern browsers but we realized that we were still having issues with older versions of Micosoft Edge and Internet Explorer.
因此,我们需要向web.config文件中的sessionState节点添加cookieSameSite ="None"属性.
So we needed to add cookieSameSite="None" attribute to sessionState node in web.config file.
<sessionState cookieSameSite="None" />
请注意此配置更改,因为较早的.net Framework版本不支持此配置更改,并导致您的网站显示错误页面.
通过这种方式,IOS 12中的浏览器仍然存在问题.但是我认为这与此已确认的错误
By the way we're still having issues with browsers in IOS 12. But I think it's related to this confirmed bug
更新2 :请参阅zemien的答案以获取有关IOS问题的可能解决方法
UPDATE 2: see zemien's answer for possible fix about IOS issue
更新3 :通过将我们的发现与zemien答案中的建议相结合,我们提出了以下重写规则.我们一直在生产中使用此配置.但是要注意:对于兼容的浏览器,它会将所有cookie标记为"SameSite:None",对于不兼容的浏览器,它会排除SameSite属性(如果存在).这似乎很复杂,但我尝试通过注释行进行解释.
UPDATE 3: By combining our findings with the suggestions in zemien's answer we've come up with the following rewrite rules. We've been using this configuration in production. But beware: it marks all the cookies with "SameSite:None" attribute for compatible browsers and excludes SameSite attribute, if exists, for incompatible browsers. It may seem complicated but I tried to explain via comment lines.
这是我们在生产中使用的最终配置:
<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>
这篇关于浏览器不会在付款网关对我们网站的发布请求中设置ASP.NET_SessionId cookie的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!