IE, iframe, P3P, Cookies, oh my
测试新浪微游戏接口时,发现一个问题:当使用IE浏览器的时候,rails的session无法保存。之前在自己开发服务器上测试时,验证过IE和Firefox都能正常使用session的,觉得很是奇怪。
通 过抓包发现,正常情况下,服务器端在响应客户端访问请求后,在返回的http头中会有Set-Cookies这样的参数,同时在接下来的客户端的http 请求头中,会加上Cookie这样的参数;上述不能正常保存session情况下的抓包分析发现,客户端的http请求头中浏览器没有设置Cookie参 数。
解决方法一:修改IE的默认Cookie设置,设置IE隐私设置中的高级隐私设置,勾选“总是允许回话Cookie”,这样session的值就能正常保存了。不过这样肯定不是最好的解决办法,对大多数用户来说,这样做不合理。
解决方法二:参考方法来自: http://www.sympact.net/2008/07/rails-and-ifram.html ,文中描述了具体原因,是因为IFrame中打开的链接和主页面的链接不在同一个域,所以IE默认会认为是不可信任的,则不允许使用Cookie。解决办 法正如文中所示,在controller中的before_filter中增加一个方法,此方法中设置响应的http相应头中增加P3P参数,问题即可解 决。 大致代码如下:
#userful gem [rack-p3p](https://github.com/hoopla/rack-p3p) # encoding: utf-8 class ApplicationController < ActionController::Base protect_from_forgery before_filter :set_p3p def set_p3p headers['P3P'] = "policyref=\"/w3c/p3p.xml\", CP=\"ALL DSP COR CURa ADMa DEVa TAIa OUR BUS IND UNI COM NAV INT\"" end end
I was just banging my head against the wall trying to figure out why internet explorer wasn’t remembering my user’s sessions. Turns out it’s something that has bitten me in the past.
IE doesn’t allow you to set cookies when your site is in an iframe unless your site has set P3P headers. Also, ordering matters – the P3P header must be set before the cookie is set.
If you’re using ruby, this gem works pretty well: https://github.com/hoopla/rack-p3p
Further reading: http://stackoverflow.com/questions/389456/cookie-blocked-not-saved-in-iframe-in-internet-explorer
All the articles I read about setting headers, etags, etc were all really old. Hopefully, if you’re using rails you found this article. Just install the gem and add the line from the README to your application.rb – no monkey patching. Good luck.
rails IE frame ActionController::InvalidAuthenticityToken
Same problem here with a rails application launched in an iframe I get:
“the change you wanted was rejected”
In log:
ActionController::InvalidAuthenticityToken
Seems that the problem occur in IE when you are developing in an iframe situation where the master page is at a different domain than the inner page. (es: iframed Facebook applications)
This is because IE’s default “medium” privacy setting has an issue with cookies in that situation.
A possible solution is to set a P3P header (try to google: p3p iframe internet explorer) Example, in application_controller.rb:
<code>before_filter <wbr>:set_p3p def set_p3p <wbr> response.headers["P3P"]='CP="CAO PSA OUR"' end</wbr></wbr></code>