您的位置:首页 > 其它

在Cookie被禁用的情况下使用url rewrite机制保持Session

2014-03-03 22:49 246 查看


在Cookie被禁用的情况下使用url rewrite机制保持Session

分类: JAVA2014-03-03
16:05 124人阅读 评论(0) 收藏 举报

Session丢失第三方cookiesurl
rewrite

最近在做QQ空间上的应用时,遇到session丢失的问题,明明把登录用户的信息存在session里了,但是再访问时,就找不到了,session是一个新的session,也就是说,每次访问都被认为是一个新的session。

寻找原因:由于我们的程序是跑在QQ空间里,是QQ空间的应用页面提供一个iframe给我们展示我们的程序页面,iframe里和iframe外分别是不同的域名,问题出在这里,跨域情况下的cookie被称作“第三方cookies”,第三方cookies是不被支持的,所以,cookie不能被顺利地带到server端,因此,靠cookie来维持的session自然就丢失了。到目前为止,我实际测试:chrome和firefox没有做限制,IE 11下,将第三方域名添加到“受信任的站点”后可以带Cookie,Safari浏览器下禁用Cookie。

但是不能要求用户去添加“受信任的站点”啊,如果仅仅针对IE浏览器,可以用P3P解决方案:

详见http://blog.csdn.net/wauit/article/details/9875157

但是P3P对Safari浏览器不起作用。

于是,我们不得不自己找解决方案了。

JAVA EE的规范说:当cookie不能用时,使用url rewrite机制来保持session。这个大家都知道,只是长时间以来,我们习惯于在cookie环境下开发,不去理会这个特性了。那么url rewrite是怎么工作的呢?

在tomcat下,默认的设置就是:优先使用cookie,如果cookie被禁用,使用url rewrite,所以,不用修改任何配置。但是我们的代码要写东西:

先说一个不太好的解决方案:response.encodeURL(String);看一下这个方法,注意,还有另外一个方法叫response.encodeUrl(String),是被弃用的API。

这个方法的功能是:把
http://xxx.com/abc?a=b
这样的url变成:
http://xxx.com/abc;jsessionid=D97956894C4330053A84DBE6FA7E8AC2?a=b
这样的url。

按理说我们应该把应用中每个链接上都套上这个方法,但是,一来太麻烦了,二来,没有判断cookie是否可用,如果cookie可用,cookie还是更好的方案,因为不必在url上带上session信息,以免拷贝分享一个URL时带上不必要的session信息。

其实,JSTL早就有解决方案,现在的JSTL也更方便使用了,我下载最新的1.2.1版本,比原来的1.1更加方便,直接加入jar包,在jsp头上引用<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>就可以使用core标签了。

<a href='<c:url value="/abc?a=b"/>'>链接</a>

生成的html:

<a href='/app/abc?abc;jsessionid=D97956894C4330053A84DBE6FA7E8AC2?a=b'>链接</a>

所以,以后不要再写href="/app/abc?a=b"这样的代码了,都用<c:url/>来代替吧,好处有:

1. 自动判断cookie是否可用,如果可用,返回原值,如果不可用,返回带jsessionid的URL

2. 自动补充ContextPath,例如我们正常应该写href="<%=request.getContextPath()%>/abc?a=b",用c:url就不用写这个context path了,直接<c:url value="/abc?a=b"/>

3. 自动对URL进行base64编码,例如

<c:url value="/abc">

<c:param name="a" value="中文"/>

</c:url>

生成的url是:/app/abc?a=%e4%b8%ad%e6%96%87'>链接</a>

在实际使用中可以先定义好,再引用,也可以直接inline在href中:

<c:url value="/abc" var="avarname">

<c:param name="a" value="中文"/>

</c:url>

<a href="${avarname}">链接</a>

或者inline:

<a href='<c:url value="/abc" var="avarname"><c:param name="a" value="中文"/></c:url>'>链接</a>

4. 可以在后面再拼想要的参数:例如:

<a href='<c:url value="/abc?a=b"/>&v=<%=new java.util.Date().getTime()%>'>链接</a>

小提示:

1. 我通常在inline使用<c:url/>时,href的值用单引号,这是为了区别里面value=""的双引号,实际上,两部分都使用双引号也是支持的。

2. 图片、css、javascript等不需要保持session的url就不要加了,一个是加大了不必要的运算量,另外,有些浏览器是异步加载的,可能你的登录存session的动作还没做完呢,图片的请求就到了,所以对这种请求做session没有意义。

3. 第三方cookies已被认识到是不安全的,虽然现在有些浏览器还没有做限制,但从趁势上看是会越来越限制的,而随着开放平台的成熟,我们的程序非常有可能有一天被放到开发平台上去运行,所以,还是要多考虑cookie禁用的情况。而且,随着集群的普遍应用,session也越来越不存在于单机了,这个是另外一个话题,session的用法将会有很大的变化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: