`

cookie和session的联系和区别

    博客分类:
  • JAVA
阅读更多

转自:http://blog.sina.com.cn/s/blog_6a0683c00100x2ua.html


【cooke机制与session机制的区别】

cookie和session都可以用来会话跟踪

cookie机制采用在客户端保持状态的方案。它是在用户端的会哈状态的存贮机制,需要用户打开客户端cookie支持。cookie的作用是为了解决http协议无状态的缺陷。

 

session机制采用的是一种在客户端与服务器之间保持状态的解决方案。由于在服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie机制来达到保存标识的目的,也可以通过如重写URL和隐藏表单域。

 

细分如下:

(1)从存取方式上比较

cookie中只能保存ASCII字符串(如果需要存取Unicode字符、二进制数数据,徐璈进行UTF-8,GBK,BASE64等方式的编码。)cookie中不能直接存取java对象。

 

session中可以存取任何类型的数据,不限于string、integer、list、map等。可以直接保存javabean乃至任何java类、对象等。可以把session看做是一个java容器类。

 

(2)隐私安全上比较

cookie存储在客户端浏览器中,对客户端是可见的,客户端的一些程序可能会窥探、复制甚至修改cookie中的内容。服务器端能够知道其中的信息。

 

seeesion存在在服务器上,对客户端来讲不存在敏感信息泄露的危险。比Cookie安全。

 

如果选用Cookie,比较好的办法是,敏感的信息如账号密码等尽量不要写到cookie中。最好是像google、baidu那样将cookie信息加密,提交到服务器后再进行解密,保证cookie中的信息只有自己能读得懂。而如果选择session就省事多了,反正是放在服务器上,session里任何隐私都可以。

 

(3)从有效期上比较

使用过google的人都知道,如果登陆过google,则google的登录消息长期有效。用户不必每次访问都重新登录,google会长久地记录该用户的登录信息。要达到这种效果,使用cookie会是比较好的选择。只需将cookie的maxage属性设为一个很大很大的数字或者integer.MAX_VALUE就可以了。

 

使用session理论上也能实现这种效果。只要条用方法setMaxInactiovInterval(Integer.MAX_VALUE)不就可以了么。但是由于session依赖于JSESSIONID的Cookie,而Cookie JSESSIONID的maxage默认为-1,只要关闭了浏览器该session就会失效,因此session不能实现永久有效的效果。使用URL地址重写也不能实现。而且如果设置session的超时时间过长,服务器累计的session就会越多,越容易导致内存溢出。

 

(4)从对服务器负担上比较

session是保存在服务器端,每个用户都会产生一个session。如果并发访问的用户非常多,会产生非常多的session,消耗大量的内存。因此想google、baidu、sina这样并发访问极高的网站,是不太可能使用session来追踪客户会话的。

 

而cookie保存在客户端,不占用服务器资源。如果并发浏览的用户非常多,cookie是很好的选择。对于google、baidu、sina来说,cookie也许是唯一的选择。

 

(5)从浏览器支持上比较

cookie需要客户端浏览器的支持,如果客户端禁用了cookie,或者不支持cookie,则会话跟踪失败,如对于wap上的应用,常规的cookie就派不上用场啦。

 

如果客户端浏览器不支持cookie,需要使用session以及URL地址重写。需要注意的是所有的用到session程序的URL都要使用response.encodeURL(String URL)或者response.encodeRedirectURL(String URL)进行URL地址重写,否则导致session会话跟踪失败。对于wap应用来说,Session+URL地址重写也许是它唯一的选择。

 

如果客户端支持cookie,则cookie既可以设为本浏览器窗口以及子窗口内有效(maxage为-1),也可以设为所有浏览器窗口内有效(maxage设为某个大于0的整数)。但session只能在本浏览器窗口以及其子窗口内有效,如果两个浏览器窗口互不相干,他们将使用两个不同的session。

 

(6)从跨域名上比较

cookie支持跨域名访问,例如将domain属性设置为“.helloweenvsfei.com”则以“.hellweenvsfei.com”为后缀的所有域名都可以访问该cookie。跨域名cookie被广泛用在网络中,例如google、baidu、sina等。而session不会支持跨域名访问。session仅在它所在的域名内有效。

 

【会话cookie和持久cookie的区别】

如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,只要关闭浏览器cookie就消失了,这种生命期为浏览器会话期的cookie被称为会话cookie。会话cookie一般不保存在硬盘上而是保存在内存里。

 

如果设置了过期时间(setMaxAge(60*60*24)),浏览器会把cookie保存在硬盘上,关闭后再次打开浏览器,这些cookie依然有效直到超过设定的过期时间。存储在硬盘上的cookie可以在不同的浏览器进程间共享。

 

【cookie简介】

Cookie是Web服务器保存在用户硬盘上的一段文本。Cookie允许一个Web站点在用户的电脑上保存信息并且随后再取回它。信息的片断以‘名/值’对(name-valuepairs)的形式储存。

 

举例来说,一个Web站点可能会为每一个访问者产生一个唯一的ID,然后以Cookie文件的形式保存在每个用户的机器上。如果您使用IE浏览器访问Web,您会看到所有保存在您的硬盘上的Cookie。它们最常存放的地方是:c:\windows\cookies(在Win2000中则是C:\DocumentsandSettings\您的用户名\Cookies——作者注)。在我的机器上共有165个文件。每一个文件都是一个由“名/值”对组成的文本文件,另外还有一个文件保存有所有对应的Web站点的信息。

 

Cookie的使用很普遍,许多提供个人化服务的网站,都是利用Cookie来辨认使用者,以方便送出使用者量身定做的内容,像是Web接口的免费E-mail网站,都要用到 Cookie。Cookie中记载的资料相有限,Cookie是安全的。网站不可能经由Cookie获得你的E-mail地址或是其它私人资料,更没有办法透过Cookie来存取你的计算机。但是如果你实在不喜欢Web服务器乱丢饼干(Cookie)到你家,当然可以让浏览器拒绝网站存放Cookie到你的计算机。只要在IE的“工具”菜单下选择“Intertnet选项”的“安全”,按自定义级别,将Cookie部分设为关闭,按确定,关闭浏览器,再重新启动浏览器即可。当你关闭Cookie之后,很多网站的个人化服务功能很可能也不能再使用了.

 

【cookie应用】

1、实现自动登录
当用户在某个网站注册后,就会收到一个惟一用户ID的cookie。客户后来重新连接时,这个
用户ID会自动返回,服务器对它进行检查,确定它是否为注册用户且选择了自动登录,从而使用户务需给出明确的用户名和密码,就可以访问服务器上的资源。

 

2、cookie应用

网站可以使用cookie记录用户的意愿。对于简单的设置,网站可以直接将页面的设置存储在cookie中完成定制。然而对于更复杂的定制,网站只需仅将一个惟一的标识符发送给用户,由服务器端的数据库存储每个标识符对应的页面设置。

 

3、使用cookie检测初访者
A.调用HttpServletRequest.getCookies()获取Cookie数组
B.在循环中检索指定名字的cookie判断cookie数组是否为空且是否存在指定的Cookie对象且值正确

C.如果是则退出循环并设置区别标识
D.根据区别标识判断用户是否为初访者从而进行不同的操作


 

注意:

(1)不能仅仅因为cookie数组中不存在特定的数据项就认为用户是个初访者。如果cookie数组为null,客户可能是一个初访者,也可能是由于用户将cookie删除或禁用造成的结果。
(2)如果数组非null,也不过是显示客户曾经到过你的网站或域,并不能说明他们曾经访问过你的servlet。其它servlet、JSP页面以及非Java Web应用都可以设置cookie,依据路径的设置,其中的任何cookie都有可能返回给用户的浏览器。
所以:正确的做法是判断cookie数组是否为空且是否存在指定的Cookie对象且值正确。


 

4、cookie记录各个用户的访问计数
(1)获取cookie数组中专门用于统计用户访问次数的cookie的值
(2)将值转换成int型
(3)将值加1并用原来的名称重新创建一个Cookie对象
(4)重新设置最大时效
(5)将新的cookie输出

 

【cookie的实现】

1、cookie的发送

(1)创建Cookie对象
(2)设置最大时效
(3)将Cookie放入到HTTP响应报头
如果你创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie:存储在浏览器的内存中,用户退出浏览器之后被删除。如果你希望浏览器将该cookie存储在磁盘上,则需要使用maxAge,并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该cookie。

发送cookie需要使用HttpServletResponse的addCookie方法,将cookie插入到一个Set-Cookie HTTP请求报头中。由于这个方法并不修改任何之前指定的Set-Cookie报头,而是创建新的报头,因此我们将这个方法称为是addCookie,而非setCookie。同样要记住响应报头必须在任何文档内容发送到客户端之前设置。

 

2、cookie的读取

(1)调用request.getCookie
要获取有浏览器发送来的cookie,需要调用HttpServletRequest的getCookies方法,这个调用返回Cookie对象的数组,对应由HTTP请求中Cookie报头输入的值。


(2)对数组进行循环,调用每个cookie的getName方法,直到找到感兴趣的cookie为止
cookie与你的主机(域)相关,而非你的servlet或JSP页面。因而,尽管你的servlet可能只发送了单个cookie,你也可能会得到许多不相关的cookie。
例如:
String cookieName = “userID”;
    Cookie cookies[] = request.getCookies();
    if (cookies!=null){
        for(int i=0;i<cookies.length;i++){
    Cookie cookie = cookies[i];
    if (cookieName.equals(cookie.getName())){
        doSomethingWith(cookie.getValue());}}}

【session在不同环境下的不同含义】

session,中文经常翻译为会话,其本来的含义是指有始有终的一系列动作/消息,比如打电话是从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session。然而当session一词与网络协议相关联时,它又往往隐含了“面向连接”和/或“保持状态”这样两个含义。

session在Web开发环境下的语义又有了新的扩展,它的含义是指一类用来在客户端与服务器端之间保持状态的解决方案。有时候Session也用来指这种解决方案的存储结构。

 

【session的机制】

当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了一个session标识(称为session id),如果已包含则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(检索不到,会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,这个SessionID是由WWW服务器随机产生的一个由24个字符组成的字符串,这个session id将被在本次响应中返回给客户端保存。之后当一个用户提交了表单时,浏览器会将用户的SessionID自动附加在HTTP头信息中,(这是浏览器的自动功能,用户不会察觉到),当服务器处理完这个表单后,将结果返回给SessionID所对应的用户。

 

保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发给服务器。一般这个cookie的名字都是类似于SEEESIONID。而比如weblogic对于web应用程序生成的cookie,JSESSIONID= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764,它的名字就是 JSESSIONID。这个JSESSIONID是存储在浏览器内存中的。

 

注意:当浏览器得到这个sessionid会将它放在自己的进程内存里,这里不同的浏览器会有所不同,IE进程间不能共享这个sessionid,也就是新开一个IE将不能共享这个sessionid;而Firefox进程间可以共享.然后你继续发请求给这个网站的时候,浏览器就会把这个sessionid放在请求头里发送给该服务器了,这样服务器得到sessionid后再和自己内存里存放的sessionid对比锁定客户端,从而区分不同客户端,完成会话. 
   可以看出如果用这种方式,当用户在会话的过程中关闭浏览器结束进程,则这个sessionid将消失,如果用户又打开浏览器想继续这次会话的时候,就会因为发送的请求中没有这个sessionid而使服务器无法辨别该把那个session信息给他,注意(这个时候服务器端的sessionid和sessionid所指向的session都还存在,只是没有正确的sessionid和它匹配而占用服务器内存,只有session过期或服务器重启才释放内存). 

上述是一种不长久的方式,为了能长久会话,就出现了持久化cookie,把cookie固化在用户的计算机上,现在的cookie不单单能存放sessionid,还能放用户信息,样式表信息等。

 

但由于cookie可以被人为的禁止,那么会话cookie和持久化cookie都不能用了,则必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。 经常被使用的一种技术叫做URL重写,就是把session id直接附加在URL路径的后面。附加方式也有两种:

(1)一种是作为URL路径的附加信息,表现形式为http://...../xxx;jsessionid= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
(2)另一种是作为查询字符串附加在URL后面,表现形式为
http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
  这两种方式对于用户来说是没有区别的,只是服务器在解析的时候处理的方式不同,采用第一种方式也有利于把session id的信息和正常程序参数区分开来。为了在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个session id。

 

注意:

常常听到这样一种误解“只要关闭浏览器,session就消失了”。实际上对于session来说,浏览器不会主动在关闭之前通知服务器它将要关闭,服务器根本不会知道浏览器已经关闭,服务器何时删除一个session,取决于sessionid的保存方式。大部分程序一般都是在用户做log off的时候发出指令去删除session。

 

(1)是因为session机制使用会话cookie来保存session id,而关闭浏览器后这个cookie消失了,seesion id也就消失了,再次连接服务器时就无法找到原来的session。

(2)如果服务器设置cookie是保存到硬盘上,或者使用某种手段改写浏览器发出的HTTP请求头,把原来的session id发送给服务器,则再次打开浏览器仍然能够找打原来的session。恰恰是由于关闭浏览器不会导致session被删除,迫使服务器为seesion设置了一个失效时间,当距离客户端上一次使用session的时间超过这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把session删除以节省存储空间。

 

【session深入理解】

1、session什么时候被创建

 一个常见的错误是以为session在有客户端访问时就被创建,然而事实是直到某server端程序(如Servlet)调用HttpServletRequest.getSession(true)这样的语句时才会被创建。

 

注意:

    如果JSP没有显示的使用 <%@page session="false"%> 关闭session,则JSP文件在编译成Servlet时将会自动加上这样一条语句HttpSession session = HttpServletRequest.getSession(true);这也是JSP中隐含的session对象的来历。

由于session会消耗内存资源,因此,如果不打算使用session,应该在所有的JSP中关闭它。

2、session何时被删除

session在下列情况下被删除:
A.程序调用HttpSession.invalidate()
B.距离上一次收到客户端发送的session id时间间隔超过了session的最大有效时间
C.服务器进程被停止

再次注意关闭浏览器只会使存储在客户端浏览器内存中的session cookie失效,不会使服务器端的session对象失效。

 

3、如何防止用户打开两个浏览器窗口操作导致的session混乱

这个问题与防止表单多次提交是类似的,可以通过设置客户端的令牌来解决。就是在服务器每次生成一个不同的id返回给客户端,同时保存在session里,客户端提交表单时必须把这个id也返回服务器,程序首先比较返回的id与保存在session里的值是否一致,如果不一致则说明本次操作已经被提交过了。

 

4、session cookie和session对象的生命周期是一样的吗

当用户关闭了浏览器虽然session cookie已经消失,但session对象仍然保存在服务器端。

 

5、打开两个浏览器窗口访问应用程序会使用同一个session还是不同的session

通常session cookie是不能跨窗口使用的,当你新开了一个浏览器窗口进入相同页面时,系统会赋予你一个新的session id,这样我们信息共享的目的就达不到了。

此时我们可以先把session id保存在persistent cookie中(通过设置session的最大有效时间),然后在新窗口中读出来,就可以得到上一个窗口的session id了,这样通过session cookie和persistent cookie的结合我们就可以实现了跨窗口的会话跟踪。

 

6、如何做到在浏览器关闭时删除session
严格的讲,做不到这一点。可以做一点努力的办法是在所有的客户端页面里使用javascript代码window.oncolose来监视浏览器的关闭动作,然后向服务器发送一个请求来删除session。但是对于浏览器崩溃或者强行杀死进程这些非常规手段仍然无能为力。

【sesseion应用】

1、如何使用会话显示每个客户的访问次数
由于客户的访问次数是一个整型的变量,但session的属性类型中不能使用int,double,boolean等基本类型的变量,所以我们要用到这些基本类型的封装类型对象作为session对象中属性的值
但像Integer是一种不可修改(Immutable)的数据结构:构建后就不能更改。这意味着每个请求都必须创建新的Integer对象,之后使用setAttribute来代替之前存在的老的属性的值。例如:
HttpSession session = request.getSession();
SomeImmutalbeClass value = (SomeImmutableClass)session.getAttribute(“SomeIdentifier”);
if (value= =null){
    value = new SomeImmutableClass(…); // 新创建一个不可更改对象
}else{
    value = new SomeImmutableClass(calculatedFrom(value)); // 对value重新计算后创建新的对象
}
session.setAttribute(“someIdentifier”,value); // 使用新创建的对象覆盖原来的老的对象


 

2、如何使用会话累计用户的数据

使用可变的数据结构,比如数组、List、Map或含有可写字段的应用程序专有的数据结构。通过这种方式,除非首次分配对象,否则不需要调用setAttribute。例如

HttpSession session = request.getSession();
SomeMutableClass value = (SomeMutableClass)session.getAttribute(“someIdentifier”);
if(value = = null){
    value = new SomeMutableClass(…);
    session.setAttribute(“someIdentifier”,value);
}else{
    value.updateInternalAttribute(…);     // 如果已经存在该对象则更新其属性而不需重新设置属性
}

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics