`
qqjavagood
  • 浏览: 94954 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

Session和Cookie的深入研究

阅读更多

    Session和Cookie的深入研究
作者:孙鑫   来源:http://www.sunxin.org  
发布者:孙鑫
时间:2009-05-25 15:07:21  

Session是一种服务器端技术,Session对象在服务器端创建,通常采用散列表来存储
信息,例如,Tomcat的Session实现采用HashMap对象来存储属性名和属性值。

Cookie是由Netscape公司发明的、用于跟踪用户会话的一种方式。Cookie是由服务器发送给客户的片段信息,存储在客户端浏览器的内存中或硬盘上,在客户随后对该服务器的请求中发回它。Session与Cookie的最大的区别是,Session在服务端保存信息,Cookie在客户端保存信息。为了跟踪用户的会话,服务器端在创建Session后,需要将Session ID交给客户端,在客户端下次请求时,将这个ID随请求一起发送回来。可以采用Cookie或URL重写的方式,将Session ID发送给客户端。在5.2.2节的基于Cookie的会话跟踪的例子中,当访问了Servlet后,关闭浏览器,再次打开浏览器访问Servlet时,可以看到开始了一次新的会话。如果我们同时打开两个浏览器,访问同一个URL,那么每一个浏览器进程都将开始一个新的会话,如图5-8所示。而在“使用Cookie的实例”中,当我们登录后,关闭浏览器,再打开浏览器,访问GreetServlet2时,直接出现了欢迎页面。然后我们同时打开两个浏览器,访问GreetServlet2时,也直接出现了欢迎页面。也就说,在5.2.2节的例子中,保存Session ID的Cookie在关闭浏览器后就删除了,不能在多个浏览器进程间共享。而在“使用Cookie的实例”的例子中,保存用户名和密码的Cookie在浏览器关闭后,再次打开,仍然存在,可以在多个浏览器进程间共享。通常,我们将用于会话跟踪的Cookie叫做会话Cookie,在Servlet规范中,用于会话跟踪的Cookie的名字必须是JSESSIONID,它通常保存在浏览器的内存中。在浏览器内存中的会话Cookie不能被不同的浏览器进程所共享。在网络上,很多人有一种错误的认识,认为以不同的方式打开浏览器窗口,或者使用其他的非IE浏览器就可以在不同的浏览器进程之间共享会话Cookie。下面,我们和读者一起看看这种错误认识是如何产生的。首先看看IE浏览器,启动Tomcat服务器,打开IE浏览器,访问5.2.2节中的例子程序,在地址栏中输入:http://localhost:8080/ch05/login,然后单击IE浏览器菜单栏上的“文件”→“新建”→“窗口”(也可以在浏览器窗口上按下Ctrl+N组合键)打开一个新窗口,分别刷新原窗口和新窗口,可以看到两个窗口中显示的Session ID是同一个。由实验可以看到,某些方式下打开的多个IE浏览器,可以共享内存中的Cookie,而另外一些方式打开的多个IE浏览器,则不能共享内存中的Cookie。再使用其他浏览器进行验证,发现有的浏览器(例如Mozilla FireFox)不管以什么方式打开窗口,都可以共享内存中的Cookie。由此,一个错误的结论就产生了:不同的浏览器对内存中的Cookie有不同的处理方式,有的浏览器(FireFox)可以在多个浏览器进程间共享会话Cookie,IE浏览器是否共享Cookie,要看浏览器打开的方式。笔者为什么会说上述结论是错误的呢?这是因为得出结论的人不了解进程的概念。读者在以上述方式打开两个IE浏览器窗口后(如果有其他的IE浏览器打开,请先关闭),同时按下Ctrl+Alt+Del组合键,选择“任务管理器”,切换到“进程”标签页,在“映像名称”下查找IEXPLORE.EXE,看看找到了几个IEXPLORE.EXE,是不是只有一个!那么这说明了什么?说明我们所看到的两个IE浏览器窗口实际上是属于同一个IE浏览器进程,难怪它们能共享内存中的会话Cookie。以其他方式打开一个IE浏览器,可以看到在“映像名称”下多了一个IEXPLORE.EXE进程,既然是两个IE浏览器进程的窗口,当然无法共享内存中的Cookie了。同样的道理,Mozilla FireFox不管以什么方式打开窗口,始终只启动了一个进程,既然这些窗口同属于一个进程,当然可以共享内存中的Cookie了。所以我们说,对于存储在内存中的Cookie,是不能被不同的浏览器进程所共享的。共享只能发生在同一个浏览器进程的不同窗口中(因为这些窗口共享同一个进程地址空间)。关于进程和线程的知识,读者可以参看相关的书籍。
对于保存在硬盘上的Cookie,因为是在外部的存储设备中存储,所以可以在多个浏览器进程间共享。有些人对Session的使用存在着一种误解,认为浏览器一旦关闭,Session就消失了。这是因为有的人看到,关闭浏览器后,再打开一个浏览器,就开始了一次新的会话,从而得出了结论。再回头看看第5.1节中的顾客在超市存包的例子,顾客存好包,购物完毕,忘了取包就走了,但存包处的管理员不知道顾客已经走了,所以他必须继续用柜子(相当于Session)存放顾客的物品,直到长时间没有人来取(Session的超时值发生),管理员才清除柜子。之所以会有“浏览器一旦关闭,Session就消失了”这种错误的认识,主要是因为保存Session ID的Cookie是存储在浏览器的内存中,一旦浏览器关闭,Cookie将被删除,Session ID也就丢失了。当再次打开浏览器连接服务器时,服务器没有收到Session ID,当然也就无法找到先前的Session,于是服务器就创建了一个新的Session。而这个时候先前的Session是仍然存在的,直到设置的Session超时时间间隔发生,Session才被服务器清除。如果我们将会话Cookie保存到硬盘上,或者通过某种技术手段改写浏览器向服务器发送的请求报头,将原先的Session ID发送给服务器,则再次打开的浏览器就能够找到原来的Session了。 我们想了解一下,用于会话跟踪的Cookie是如何创建的,为何只能保存在浏览器的内存中,而不能保存到用户的硬盘上。在Tomcat 6.0.16.中,Session的创建是调用org.apache.catalina.connector.Request类中的doGetSession()方法来完成的。下面我们给出这个方法的代码片段: Java代码

1.protected Session doGetSession(boolean create)
2.{
3.    …
4.    // Creating a new session cookie based on that session
5.    if ((session != null) && (getContext() != null)
6.           && getContext().getCookies())
7.    {
8.        Cookie cookie = new Cookie(Globals.SESSION_COOKIE_NAME,
9.                                           session.getIdInternal());
10.        configureSessionCookie(cookie);
11.        response.addCookieInternal(cookie);
12.    }
13.
14.    if (session != null)
15.    {
16.        session.access();
17.        return (session);
18.    }
19.    else
20.    {
21.        return (null);
22.    }
23.}
24.
25.protected void configureSessionCookie(Cookie cookie)
26.{
27.    cookie.setMaxAge(-1);
28.    String contextPath = null;
29.    if (!connector.getEmptySessionPath() && (getContext() != null))
30.    {
31.        contextPath = getContext().getEncodedPath();
32.    }
33.    if ((contextPath != null) && (contextPath.length() > 0))
34.    {
35.        cookie.setPath(contextPath);
36.    }
37.    else
38.    {
39.        cookie.setPath("/");
40.    }
41.    if (isSecure())
42.    {
43.        cookie.setSecure(true);
44.    }
45.}

代码的第8行,我们看到非常熟悉的创建Cookie对象的代码,Cookie的名字是Globals.SESSION_ COOKIE_NAME,SESSION_COOKIE_NAME被定义为静态的常量,其值为JSESSIONID。Cookie的值是调用session.getIdInternal ()得到的Session ID。第10行,调用了configureSessionCookie()方法来配置会话Cookie。我们转到configureSessionCookie()方法中,第27行,调用Cookie对象的setMaxAge()方法设置Cookie的生存时间,在“使用Cookie的实例”的例子中,我们说过,如果时间值为负数,那么当客户端的浏览器退出,Cookie将会被删除。看到这儿,我们就知道了为什么会话Cookie只能保存在内存中了,这是由Tomcat的实现决定的。第35行,调用Cookie对象的setPath()方法,指定这个Cookie在当前Web应用程序的上下文路径下有效。学习方法:我们在学习的时候,不仅要通过实验来掌握知识,更重要的是要思考、理解实验结果产生的原因,从现象看本质,这样才不至于得出错误的结论。然而,由于我们所掌握的知识是有限的,有时候又难免犯这样或那样的错误,这不要紧,关键是要养成学习与思考的习惯,这样才能获得更大的进步。

 
0
0
分享到:
评论

相关推荐

    深入探究Django中的Session与Cookie

    周末小闲在家研究了下django的 cookie 和 session,所以下面这篇文章主要给大家深入地介绍了关于Django中Session与Cookie的相关资料,文中通过示例代码介绍的非常详细,需要的朋友们下面跟着小编来一起看看吧。

    spring Scurity终于测试OK了

    pring Scurity终于测试OK了,复杂的功能还待深入研究!发布出来一起探讨吧! 就是因 为研究它,我的个天啦!头都大了一圈!还待修改完整版!我的目标不是每个项目拿到它就能使用!到时再说啦。。。 虽然只是一个...

    NetworkMiner开源的数据包抓取,协议分析嗅探

    一款开源的网络取证和协议分析工具,能够通过嗅探器检测操作系统、主机名以及开放的端口。同时也可以通过分析pcap文件来获取到数据包的详细信息...如果想深入研究数据包结构分析和Pcap的话NetworkMiner也是个不错的选择

    深入体验Java Web开发内幕

     本书适合所有Web应用的开发人员、Java程序员在工作和学习中参考阅读,也适合作为相关专业本科生、研究生的学习参考资料,也可作为相关培训机构的培训教材。 【作者简介】  张孝祥中国著名IT培训教育...

    李兴华 Java Web 开发实战经典_带源码_高清pdf 带书签 上

    6.2.5、深入研究page属性范围 6.3、request对象 6.3.1、乱码解决 6.3.2、接收请求参数 6.3.3、显示全部的头信息 6.3.4、角色验证 6.3.5、其他操作 6.4、response对象 6.4.1、设置头信息 6.4.2、页面跳转 ...

    MLDN+李兴华+Java+Web开发实战经典.part3.rar )

    6.2.5、深入研究page属性范围 6.3、request对象 6.3.1、乱码解决 6.3.2、接收请求参数 6.3.3、显示全部的头信息 6.3.4、角色验证 6.3.5、其他操作 6.4、response对象 6.4.1、设置头信息 6.4.2、页面...

    李兴华 java_web开发实战经典 源码 完整版收集共享

    6.2.5、深入研究page属性范围 6.3、request对象 6.3.1、乱码解决 6.3.2、接收请求参数 6.3.3、显示全部的头信息 6.3.4、角色验证 6.3.5、其他操作 6.4、response对象 6.4.1、设置头信息 6.4.2、页面跳转 ...

    李兴华 Java Web 开发实战经典_带源码_高清pdf 带书签 下

    6.2.5、深入研究page属性范围 6.3、request对象 6.3.1、乱码解决 6.3.2、接收请求参数 6.3.3、显示全部的头信息 6.3.4、角色验证 6.3.5、其他操作 6.4、response对象 6.4.1、设置头信息 6.4.2、页面跳转 ...

    李兴华Java Web开发实战经典.pdf (高清版) Part1

    6.2.5、深入研究page属性范围 6.3、request对象 6.3.1、乱码解决 6.3.2、接收请求参数 6.3.3、显示全部的头信息 6.3.4、角色验证 6.3.5、其他操作 6.4、response对象 6.4.1、设置头信息 6.4.2、页面...

    李兴华 Java Web 开发实战经典 高清扫描版Part3

    6.2.5、深入研究page属性范围 6.3、request对象 6.3.1、乱码解决 6.3.2、接收请求参数 6.3.3、显示全部的头信息 6.3.4、角色验证 6.3.5、其他操作 6.4、response对象 6.4.1、设置头信息 6.4.2、页面跳转 ...

    李兴华Java Web开发实战经典(高清版) Part2

    6.2.5、深入研究page属性范围 6.3、request对象 6.3.1、乱码解决 6.3.2、接收请求参数 6.3.3、显示全部的头信息 6.3.4、角色验证 6.3.5、其他操作 6.4、response对象 6.4.1、设置头信息 6.4.2、页面...

    java web 视频、电子书、源码(李兴华老师出版)

    6.2.5、深入研究page属性范围 6.3、request对象 6.3.1、乱码解决 6.3.2、接收请求参数 6.3.3、显示全部的头信息 6.3.4、角色验证 6.3.5、其他操作 6.4、response对象 6.4.1、设置头信息 6.4.2、页面...

    asp.net知识库

    深入剖析ASP.NET组件设计]一书第三章关于ASP.NET运行原理讲述的补白 asp.net 运行机制初探(httpModule加载) 利用反射来查看对象中的私有变量 关于反射中创建类型实例的两种方法 ASP.Net应用程序的多进程模型 NET委托...

Global site tag (gtag.js) - Google Analytics