cookie跨域的问题,是一个老生长谈的话题了,在博客园中一搜就能搜出一大把相关文章。
今天和同事讨论跨域问题时,偶然发现在IE在跨域请求时的一个Bug,特记录,并分享。
跨二级域名就不说了,下面的各个案例是在跨一级域名时出现的,以下是问题重现步骤。
准备工作
在passport.com站点中有一个处理程序,我们暂且叫它sso.ashx,用来输出passport.com域名下的Id为userName的cookie
在appA.com站点中有一个页面,我们暂且叫它userInfo.aspx,用它来请求passport.com中的sso.ashx并获取它的输入。
sso.ashx中关键代码如下:
HttpCookie cookie = context.Request.Cookies["userName"];
string userName = cookie == null ? "" : cookie.Value;
context.Response.Write("var user='" + userName +"';");
appA.com的userInfo.aspx关键代码如下:
<script>
document.write(user);//user变量在sso.ashx在输出内容中定义
</script>
我们看到,预期的效果应该是,在passport.com中设置上id为userName的cookie之后,在访问http://appA.com/userInfo.aspx 时,应该可以正常获取到这个cookie的值。
案例一
在passport.com站点下先添加一个过期时间不设置的userName cookie,比如值为"Jim Green",然后在appA.com站点的页面userInfo.aspx中访问passport.com站点中的sso.ashx。在IE、火狐、Chrome下,均可以正确获取。
添加cookie代码:
案例二
清除passport.com站点下的所有cookie,添加一个设置了过期时间为当前日期+4小时的cookie,比如值为“John”,然后在appA.com站点的页面userInfo.aspx中访问passport.com站点的sso.ashx,在火狐、Chrome下正常,均可以正常访问,在IE下,完蛋了,无法访问。
添加cookie代码:
案例三
同案例二,将passport.com和appA.com两个站点添加到信任站点,并将信任站点的安全级别设置为低,然后访问appA.com站点的userInfo.aspx,不错,也可以正确获取。
结语
通过以上三个案例,可以得知,IE对于跨域请求cookie做了比较严格的限制,也许不叫严格,叫变态。或者,我们可以叫它为Bug。
不然,如何说你IE就是不允许跨域访问,或者说只有在设置安全级别为低的请问下才可以跨域访问,那么为什么一个不设置过期时间的cookie却可以在任何级别下都可以被跨域呢?
如何既要设置过期时间,又要在IE下可以跨域访问,怎么办?可以这样做:在appA.com站点的userInfo.aspx的页面响应头中,加上P3P这个响应头。加上之后,再请求passport.com站点的sso.ashx时,就会将passport.com站点下的cookie带过去,在passport.com的sso.ashx中也可以获取到已定义cookie了。
这么多年过去了,IE依然保持着自己的一套标准。
淘宝的SSO登录,在IE下是存在点小问题的。
附P3P响应头:
P3P: CP="NON DSP COR CURa ADMa DEVa TAIa PSAa PSDa IVAa IVDa CONa HISa TELa OTPa OUR UNRa IND UNI COM NAV INT DEM CNT PRE LOC“
参考
P3P概念: http://wiki.chinabaike.com/index.php?doc-view-42793
跨二级域名: http://www.cnblogs.com/silicon-fado/archive/2009/03/15/1412226.html
P3P解决cookie存取的跨域问题:http://www.cnblogs.com/love2wllw/archive/2010/04/09/1708585.html