【问题标题】:Cross-domain iframe causes troubles with cookies (Rails)跨域 iframe 导致 cookie 出现问题(Rails)
【发布时间】:2015-03-31 05:56:42
【问题描述】:

我们最近完成了为客户创建的电子学习课程,并计划很快将其部署到生产环境中。 他们有自己的网络服务器和自己的域,但希望我们在我们的服务器上运行的 Rails 驱动的 LMS 上托管课程。

课程很长,需要注册才能随时暂停和继续。

现在,他们还希望用户访问他们的域 foo.com,浏览并启动课程。然后,课程启动器页面将我们的页面嵌入到 iframe 中,来自 app.bar.com。

这当然会导致会话出现一些问题,因为第三方 cookie 等等。我调查并发现了大量不同的黑客和解决方案,但到目前为止都没有奏效。

  1. 据我所知,P3P-header 已不再真正使用,但我添加了一个虚拟头,类似于 Facebook 和 Google。 (P3P: CP="This site does not have a p3p policy.")

  2. 我还研究了CORSAccess-Control-Allow-Credentials: true 听起来很有希望,但什么也没做。我可能配置错误,但想知道在投入太多时间之前是否有可能。

  3. 一些网站提到,如果浏览器之前与 app.bar.com 通信,它可以工作,所以我尝试在 iframe 之前从 app.bar.com 加载图像,但这还不够,或者还有另一个 hack后来修好了。

我了解阻止第三方 Cookie 通常对于阻止跟踪用户是件好事。打算参加该课程的人来自世界各地,因此无法解释如何为每个人禁用第三方 cookie 拦截。

我考虑的另一件事是从客户端获取一个指向我们服务器的子域,course.foo.com 或类似的东西,并且从那里请求数据的 iframe 可以工作。在尝试通过该请求之前,我想知道它是否会起作用。

域之间不需要任何类型的通信,正如大多数其他 JavaScript 解决方案似乎假设的那样,除了确保设置 cookie 并将其发送到我们的 LMS。

我可以完全控制我们的服务器,并且可以根据需要更改其中的大部分内容。对于客户端服务器,我只能有限地访问 HTML。

编辑:刚刚注意到至少在 IE9 中,它与 P3P-header 配合得很好。

【问题讨论】:

  • 我有类似的问题。如果我能够在没有 cookie 的情况下捕获 POST 并共享链接以直接在我的网站上的窗口中显示表单,那么这对我有用... (stackoverflow.com/questions/29311728/…)

标签: ruby-on-rails iframe cookies


【解决方案1】:

最安全的方法确实是在客户域的子域上运行您的应用程序,即。 course.foo.com.

P3P 从未获得太多认可。您在 3) 中提到的“首先与网站沟通”部分可能指的是Safari loophole that has since been closed

CORS 不适用于您的情况。如果您想从客户父框架与课程站点进行交互,这将是相关的,例如。发出 AJAX 请求或加载字体等资源。

因此,如果您希望用户代理将 cookie 视为第一方 cookie,

  1. 在 course.foo.com 上托管网站
  2. config/initializers/session_store.rb中的设置改为

    Rails.application.config.session_store :cookie_store, 
                                           key: '_course_session',
                                           domain: 'foo.com'
    

默认情况下,Rails 会将 cookie 域设置为 course.foo.com,它与 foo.com 的来源不同。但反过来也可以——通过将 cookie 域设置为 foo.com,它可以被每个子域访问并且与每个子域相同,例如 www.foo.comcourse.foo.com

不过,这有一个潜在的安全考虑:您的课程应用 cookie 现在也可用于您客户的现有网站,因此那里的安全问题现在也可能危及您的应用会话 cookie。

【讨论】:

  • 我相信您实际上希望将域设置为".foo.com"。否则,应将其视为完全限定名称,并且不应发送 cookie。
  • @DavidHoelzer 使用 RFC 6295 进行了修订:请注意,如果存在前导 %x2E (“.”),即使该字符不允许,也会被忽略。没有前导点的域适用于子域——几乎是 IE 从一开始就处理它的方式。
  • 谢谢!我错过了这个变化!
【解决方案2】:

您是否在其他域上添加了以下标头:

'Access-Control-Allow-Origin:*'

或者理想情况下只设置源的域。 如果您阅读了我的评论,似乎您想传递存储在 cookie 中的变量,那么为什么不使用基于用户唯一密钥的加密并通过 GET 传递数据:

<iframe src="http://mywebsite.com?user_id=[id]&user_data=[encrypted_data_goeshere]">

当然你已经考虑到安全性,不允许人们操纵这个 url 来利用你的程序。

【讨论】:

  • 应该添加到哪一边?我无法更改客户端发送的标头,只能在我们这边……
  • 当它被加载到您的客户端 iframe 以及任何 Ajax/JS 请求中时,它应该是您网站服务器的标头。但是忘记这一点,你做这一切都错了。向我解释一下究竟需要在域之间传递什么,他网站上的会话 cookie 在您的服务器上没有任何意义,所以您试图传递一个存储在会话中的变量?这与同源策略无关。会话存储在服务器端,只有一个 cookie 作为唯一 ID 来查找它。实际数据不存储在 cookie 中!
  • 实际上不需要在域之间传递任何东西。包含页面(由客户端托管)只是一个愚蠢的静态 HTML 容器,而 iframe(由我们托管)的内容包含课程启动器和登录位。问题是,如果访问者在 iframe 中填写登录表单,我们的服务器会发送标头以设置带有会话 ID 的 cookie,但访问者在 iframe 中加载新页面时拒绝将其发送回,因此保持登录状态in 不起作用。
  • 我认为如果您在 iframe 之外加载页面并尝试登录,您将遇到同样的问题。让我知道如果我错了,你试过吗?您要在 iframe 中从同一个域/子域发布一个表单?
  • 如果我尝试在 iframe 中登录,然后访问 iframe 之外的页面,我仍然处于退出状态。如果我访问 iframe 之外的页面,然后登录,它可以正常工作。 iframe 中的页面来自和发往相同的域,
猜你喜欢
  • 2012-04-11
  • 1970-01-01
  • 2012-03-12
  • 2012-12-11
  • 2011-02-18
相关资源
最近更新 更多