我有一个Rails 6.1应用程序,它使用会话来存储一些数据。当我在iFrame中打开应用程序时,会话不起作用(当导航到应用程序的另一个页面时,我无法获得它们的值,仍然在相同的iFrame中)
我读了很多关于这个的文章,并摆弄了cookiesame_site
配置等。
我也读到Chrome是原因,但我在Safari中尝试了同样的问题。
但是我不想在rails应用程序和包含iFrame的页面之间共享会话。我只是想让应用程序在iFrame内正常工作。
你知道是什么原因吗?
为了让你的会话cookie在iframe中工作,你需要显式地将它的SameSite
设置为None
。
Rails版本≥6.1
Rails 6.1引入了一个新的配置选项,您可以在config/application.rb
中设置它:
config.action_dispatch.cookies_same_site_protection = :none
指南的相关部分在这里。
Rails版本<6.1
最好的方法是使用rails_same_site_cookie gem。
Secure
设置
当将SameSite
设置为None
时,您还必须确保将Secure
设置为true
时发送cookie。当您取消config/environments/production.rb
中的以下行注释时,就会发生这种情况:
config.force_ssl = true
这个变化是从哪里来的?
Rails 6.1的相关提交在这里。这归结为Rails现在显式地为它发送的每个cookie设置SameSite=Lax
。
我发现本地测试设置的最佳方法是运行一个单独的服务器(例如Middleman实例)来模拟将Rails应用程序嵌入iframe中的第三方页面。
然后您可以将一个浏览器选项卡指向localhost:3000/my/iframed/page
,另一个指向lvh.me:4567/my/embedding/page
。您应该能够登录一个选项卡,并在另一个选项卡中充当已登录的用户。
在类似生产的环境中进行测试也是至关重要的。
None
vsLax
vsStrict
如果你要设置SameSite=Lax
,这个设置只会在两个选项卡都指向相同的域时起作用,例如localhost
。对于SameSite=Strict
,它根本不起作用。
当你在测试时,如果你从例如:lax
切换回:none
,你将从两个选项卡注销。
响应头
注意,更改SameSite
的值不足以设置您的Rails应用程序在iframe中工作。您还需要在相关的控制器动作中设置正确的标头,如下所示:
response.set_header("X-Frame-Options", "ALLOW-FROM #{embedding_url}")
response.set_header("Content-Security-Policy", "frame-ancestors 'self' #{embedding_url}")
embedding_url
可以是*
,如果你想让任何人都能够通过iframe嵌入你的Rails应用程序。
为了进一步阅读,makandra的好心人专门编制了一张关于SameSite设置的卡片。