Rail, ajax and iframe in Safari



在我们的应用程序中,我们有一些使用ajax的元素。我们为用户提供在iframe中嵌入部分应用程序的功能。

在Chrome和Mozilla中一切都很好。在Safari中,我们得到422错误,服务器日志看起来像这样:

2015-07-15T08:26:06.818885+00:00 app[web.1]: Completed 422 Unprocessable Entity in 4ms
2015-07-15T08:26:06.815411+00:00 app[web.1]: Can't verify CSRF token authenticity
2015-07-15T08:26:06.823389+00:00 app[web.1]: ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):

我们发现,如果我们直接访问iframe url,然后到包含iframe的页面,它工作得很好,这可能表明它与cookie有关。

我尝试了这个方法,但是我们还是有这个问题。

Safari(默认情况下)不允许在iframe中设置cookie,除非用户已经访问过该站点。想象一下这个代码:

# a.com
<iframe src="b.com/iframe">

如果你直接访问b.com(任何页面)并且它设置了一个cookie,那么Safari将在你访问a.com时发送该cookie,并且iFrame到b.com被加载。

但是,如果您访问a.com而没有首先访问b.com,则Safari将忽略b.com/iframe尝试设置的任何cookie。

解决方案在"safari的解决方案"一节中有描述(如果链接不起作用,这里是web存档保存的版本)。

  1. 检测是否支持cookie
  2. 如果没有,在页面上加上"此站点需要cookie"。请按此继续。
  3. 当用户点击链接/按钮时,打开一个弹出窗口,它会设置一个cookie并关闭自己。在台式机上,你可以把弹出窗口设置得相当小而无害。在移动设备上,它更难看,因为你不能把弹出窗口设置得比全屏小。然而,无论哪种方式,弹出窗口只在屏幕上停留不到一秒钟。
  4. iframe重新加载自己,现在可以使用cookie了。

最后我发现Safari不允许在iframe中保存cookie。

这意味着如果你需要使用cookie,你需要做一些事情。

我找到的解决方案是:

    在iframe代码中检查session[:safari_cookie_fixed]是否存在。如果没有,渲染一个代码,将使用postMessage与父窗口通信,并让他知道我们需要重定向。
  1. 当iframe被加载时,父窗口通过postMessage向iframe发送信号。侦听器,它是在cookie不存在的情况下呈现的,发送一个信号到父节点执行重定向,父节点重定向到iframe域中的/set-cookie页面,将其当前url添加为查询字符串参数。
  2. set_cookie action保存cookie safari_cookie_fixed并重定向回父页面(其url在查询字符串中可用)

当然这个解决方案需要在父页面中添加一些js代码,但是当你给你的用户iframe html代码时,你也可以包含js。

最新更新