浅谈Cookie与Session

  前几天接触了一个实现自动登陆的项目,其中涉及到了Cookie和Session的相关知识,突然发现,虽然本身常用Cookie和Session,但对二者的原理和联系却知之甚少,特写一篇博客来总结一下。html

Cookie

Cookie的产生背景

  在web应用中,会话跟踪是很重要的。一个用户的全部请求操做都应该属于同一个会话。 例如,在网上商城中,用户A购买的商品都应该放在A的购物车内,而不能放在用户B或C的购物车内,由于它们不属于同一个会话。
  众所周知,web应用是使用HTTP协议传输数据的,而HTTP协议是无状态的。这里稍微解释一下HTTP协议的无状态特性:浏览器的每一次请求,服务器都会独立处理,不与以前或以后的请求产生关联,也就是说,浏览器的每一次请求,对服务器来讲都是全新的。这个过程能够用下图说明:
web

图片未加载成功
   一旦数据交换完毕,客户端与服务器端的链接就会关闭,再次交换数据须要创建新的链接,这就意味着服务器没法从链接上跟踪会话。 即用户A购买了一件商品放入购物车内,当再次购买商品时,服务器已经没法判断该购买行为是属于用户A的会话仍是用户B的会话了。要跟踪该会话,必须引入一种机制,因而Cookie就应运而生了。Cookie由W3C组织提出,最先由Netscape社区发展,目前全部的主流浏览器都支持Cookie。

Cookie的工做原理

  上面说到因为HTTP协议的无状态特性,服务器没法从链接上知道客户身份。解决办法就是给客户端颁发一个“通行证”,不管谁访问都必须携带本身的通行证,这样服务器就能从通行证上确认客户身份了,这就是Cookie的工做原理。
  Cookie其实是一小段文本信息。客户端请求服务器,若是服务器须要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie,在Servlet中即调用response.addCookie(Cookie cookie)方法。客户端浏览器会把Cookie保存起来,当浏览器再次请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器,服务器检查该Cookie,从而得到用户身份信息。服务器还能够根据须要修改Cookie的内容。跨域

Cookie的机制

  Cookie机制采用的是在客户端保持状态的方案。 当服务器调用addCookie方法向浏览器颁发Cookie,本质上是在HTTP的响应头中加上一行特殊的指示以提示浏览器按照指示生成相应的Cookie,保存在客户端,里面记录着用户当前的信息。当用户再次访问服务器时,浏览器检查全部存储的Cookie,若是某个Cookie所声明的做用范围大于等于将要请求的资源所在的位置,则把该Cookie附在请求资源的HTTP请求头上发送给服务器,服务器根据该Cookie得到用户身份信息。浏览器

Cookie相关问题

Cookie的生命周期

  在讨论Cookie的生命周期以前,先说一下setMaxAge(int maxAge)方法,该方法用于设置Cookie的失效时间。
  若是maxAge为正数,则表示该Cookie会在maxAge秒以后自动失效。浏览器会将maxAge为正数的Cookie持久化,即写到对应的Cookie文件中。不管客户关闭了浏览器仍是电脑,只要还在maxAge秒以前,登陆网站时该Cookie仍然有效。
  若是maxAge为负数,则表示该Cookie仅在本浏览器窗口以及本窗口打开的子窗口内有效,关闭窗口后该Cookie即失效。maxAge为负数的Cookie,为临时性Cookie,不会被持久化,不会被写到Cookie文件中。Cookie信息保存在浏览器内存中,所以关闭浏览器该Cookie就消失了。Cookie默认的maxAge值为–1。tomcat

Cookie的修改和删除

  Cookie并不提供修改、删除操做。若是要修改某个Cookie,只须要新建一个同名的Cookie,添加到response中覆盖原来的Cookie便可。
  若是要删除某个Cookie,能够将Cookie的maxAge属性设置为0;也能够新建一个同名的Cookie,并将maxAge设置为0,并添加到response中覆盖原来的Cookie。maxAge为0的Cookie即失效Cookie,会被浏览器从Cookie文件或者内存中删除。
  注意:修改、删除Cookie时,新建的Cookie除value、maxAge以外的全部属性,例如name、path、domain等,都要与原Cookie彻底同样。不然,浏览器将视为两个不一样的Cookie不予覆盖,致使修改、删除失败。安全

Cookie的不可跨域名性

  不少网站都会使用Cookie,例如,Google会向客户端颁发Cookie,Baidu也会向客户端颁发Cookie。可是浏览器访问Google只会携带Google的Cookie,而不会携带Baidu的Cookie;Google也只能操做Google的Cookie,而不能操做Baidu的Cookie。这是由Cookie的隐私安全机制决定的,隐私安全机制可以禁止网站非法获取其余网站的Cookie,即Cookie的不可跨域名性。
  Cookie在客户端是由浏览器来管理的,浏览器可以保证Google只会操做Google的Cookie而不会操做Baidu的Cookie,从而保证用户的隐私安全。浏览器判断一个网站是否能操做另外一个网站Cookie的依据是域名,Google与Baidu的域名不同,所以Google不能操做Baidu的Cookie。
  须要注意的是,用户登陆网站 www.google.com 以后会发现访问 images.google.com 时登陆信息仍然有效,两者虽然同属于Google,可是域名不同,一样不能互相操做彼此的Cookie,这是由于Google作了特殊处理。想让同一个一级域名下的两个二级域名能交互使用Cookie,须要设置Cookie的domain参数。例如想全部 wsghawk.com 名下的二级域名均可以使用该Cookie,能够这么写:cookie.setDomain(".wsghawk.com"); 注意,domain参数必须以点(".")开始。服务器

Cookie的路径

  domain属性决定容许访问Cookie的域名,而path属性决定容许访问Cookie的路径(ContextPath)。例如,若是只容许/hawk/下的程序使用Cookie,能够这么写:cookie.setPath("/hawk/"); 设置为“/”时容许全部路径使用Cookie,path属性须要使用符号“/”结尾。cookie

Session

Session的工做原理

  Session是另外一种记录客户状态的机制,不一样的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,这就是Session。客户端浏览器再次访问时只须要从该Session中查找该客户的状态就能够了。
  若是说Cookie机制是经过检查客户身上的“通行证”来肯定客户身份的话,那么Session机制就是经过检查服务器上的“客户明细表”来确认客户身份。Session至关于程序在服务器上创建的一份客户档案,客户来访的时候只须要查询客户档案表就能够了。dom

Session的机制

  Session机制采用的是在服务器端保持状态的方案。 当用户访问到一个服务器,服务器就要为该用户建立一个Session,在建立这个Session的时候,服务器首先检查这个用户发来的请求里是否包含了一个SessionId,若是包含了一个SessionId则说明以前该用户已经登录过并为此用户建立过Session,那服务器就按照这个SessionId把这个Session在服务器的内存中查找出来(若是查找不到,就有可能为它新建立一个)。若是客户端请求里不包含有SessionId,则为该客户端建立一个Session并生成一个与此Session相关的SessionId。这个SessionId是一个惟一的、不重复的字符串,这个SessionId将被在本次响应中返回到客户端保存,而保存这个SessionId的正是Cookie。 这样在交互过程当中浏览器能够自动的按照规则把这个标识发送给服务器。网站

Session相关问题

Session的生命周期

  以前我一直认为,一个浏览器窗口被打开是建立一个Session,而关闭浏览器窗口时该Session就会被删除,其实这是错误的! 实际上直到某服务器端程序调用 HttpServletRequest.getSession(true); 这样的语句时Session才被建立。而除非程序通知服务器删除Session,不然Session会被服务器一直保留,直到Session的失效时间到了自动删除。服务器是不知道浏览器是否被关闭的。
  以前会产生这种错觉的缘由是:通常Session机制都使用Cookie来保存SessionId,而一旦关闭浏览器,SessionId就不存在了,再链接服务器时就找不到原来的Session了。若是服务器设置的Cookie被保存到硬盘上,或者使用某种手段改写浏览器发出的HTTP请求头,把原来的SessionId发送给服务器,则再次打开浏览器仍然可以找到原来的Session。因为关闭浏览器不会致使Session被删除,迫使服务器为Seesion设置了一个失效时间,当距离客户端上一次使用Session的时间超过这个失效时间时,服务器就能够认为客户端已经中止了活动,才会把Session删除以节省存储空间。
  通常状况下,Session都是存储在内存里,当服务器进程被中止或者重启的时候,内存里的Session也会被清空。若是设置了Session的持久化特性,服务器就会把Session保存到硬盘上,当服务器进程从新启动或这些信息将可以被再次使用(tomcat在shutdown前默认会自动将Session保存到指定的目录中,所以tomcat从新启动后,Session是能够继续使用的)。

Session对浏览器的要求

  SessionId为服务器自动生成的,它的maxAge属性通常为–1,表示仅当前浏览器内有效,而且各浏览器窗口间不共享,关闭浏览器就会失效。所以同一机器的两个浏览器窗口访问服务器时,会生成两个不一样的Session。可是由浏览器窗口内的连接、脚本等打开的新窗口(也就是说不是双击桌面浏览器图标等打开的窗口)除外,这类子窗口会共享父窗口的Cookie,所以会共享一个Session。注意:新开的浏览器窗口会生成新的Session,但子窗口除外,子窗口会共用父窗口的Session。
  洋洋洒洒写了很多了,其实目前企业流行的方式仍是在请求头中携带token来进行身份验证,由于Session会占用服务器较多的内存空间,影响效率。其实最后还应该写一写Servlet中与Cookie和Session有关的API,但感受以我这种事无巨细的办事风格又要写好久,仍是你们本身去查阅参考文档吧<(^-^)>!
  如对文章内容有疑问或发现其中的错误,请在评论区留言。

参考文章

WEB应用中的SESSION知多少?
Cookie/Session机制详解

相关文章
相关标签/搜索