为了让您的会话 cookie 在 iframe 中工作,您需要将其 SameSite 设置显式设置为 None。
Rails 版本 ≥ 6.1
Rails 6.1 引入了一个新的配置选项,您可以设置它,例如在你的config/application.rb:
config.action_dispatch.cookies_same_site_protection = :none
指南的相关部分是here。
Rails 版本
您最好的选择是最有可能使用rails_same_site_cookie gem。
Secure 设置
将SameSite 设置为None 时,您还必须确保在发送您的cookie 时将Secure 设置设置为true。当您取消注释 config/environments/production.rb 中的以下行时会发生这种情况:
config.force_ssl = true
这个变化来自哪里?
Rails 6.1 的相关提交是here。它归结为 Rails 现在在它发送的每个 cookie 上显式设置 SameSite=Lax。
测试
我发现在本地测试这种设置的最佳方法是运行单独的服务器(例如 Middleman 实例)来模拟将 Rails 应用程序嵌入 iframe 的第三方页面。
然后您可以将一个浏览器选项卡指向localhost:3000/my/iframed/page,将另一个指向lvh.me:4567/my/embedding/page。您应该能够登录一个选项卡并在另一个选项卡中充当已登录用户。
在类似生产的环境中进行测试也很重要。
None vs Lax vs Strict
如果您要设置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}")
如果您希望任何人都能够通过 iframe 嵌入您的 Rails 应用程序,embedding_url 可以是 *。
为了进一步阅读,makandra 的好心人已经编译了 a card 专门关于 SameSite 设置的信息。
Safari 支持
除了要求您的用户取消选中其首选项中的防止跨站点跟踪复选框之外,您无法解决 Safari 中的问题。未来,这可能适用于所有主要浏览器(有关 Chrome 博客文章,请参阅here)。