1、为什么有Session和Cookie
根据早期的HTTP协议,每次request-reponse时,都要重新建立TCP连接。TCP连接每次都重新建立,所以服务器无法知道上次请求和本次请求是否来自于同一个客户端。因此,HTTP通信是无状态的。服务器认为每次请求都是一个全新的请求,无论该请求是否来自同一地址。
但是这也带来了问题,假如不使用Session或Cookie,那么就意味着假如你登录了某个购物网站,你的每次请求因为无状态,购物网站的服务器都无法判断你的身份和登陆与否,意味着为了保持登陆你必须浏览某个商品时登陆一次,浏览另一个商品又要登陆一次。
这种用户体验谁还愿意上购物网站?于是出现了Cookie,它把少量的用户信息存储在用户自己电脑上,因为它在同一个域名下是全局的,所以用户访问时,服务器就可以从该域名下任意页面读取Cookie中的信息,以判断登陆状态。
但Cookie存在用户端,存储尺寸也有大小限制,用户自身还可以禁用,甚至可见并修改,安全性极差。为了安全,又能方便地读取全局信息,于是出现了新的存储会话机制,Session。
2、Session们谁是谁的谁(实现机制)
有了Session,就能让用户在一次会话中的多次HTTP请求产生关联,让多个页面都能读取到Session域里面的值。Session信心存放在服务器端,也很好地解决了安全问题。
但是同样有疑问,若干客户端和服务器连接,服务器会为每个客户端的一次会话创建一个会话对象Session,如何区分哪个Session对应的是哪个客户端呢?
答案是,多数容器是采用Cookie机制来实现Session机制,也就是说,利用Cookie来保存 “客户端” 和 “服务器里会话对象” 之间的对应关系。
使用Cookie实现会话机制的过程是:
- 当容器创建一个新的HttpSession对象后,会生成一个随机数,称之为会话ID,并将ID值封装成一个名为JSESSIONID的Cookie,返回给客户端;
- 之后的请求,在调用request.getSession方法获得会话对象时,容器会先从request中获取JSESSIONID的值,根据值查找到对应的会话对象,返回使用;
- 如果没有获得JSESSIONID值,则容器认为当前请求没有相关联的会话对象,会重复第一步进行生成。
实际上,整个过程很像点餐:
- 去餐馆点了牛排,得到号码牌(JSESSIONID)
- 你走开了几步之后,服务员就忘了你是谁
- 你如果想取你的牛排,你就需要这个号码牌去找服务员领
- 服务员能根据号码牌确认你是顾客,你点过餐,把你对应的牛排拿给你
3、Cookie被阻止的处理
Cookie在浏览器设置是可以被阻止的,那么根据其Session的实现机制,如果Cookie被禁用,那么Session也会受到影响。
Cookie被阻止,那么根据其实现机制,则找不到JSESSIONID的Cookie,会认为是首次登陆,所以无法利用Session保持用户的登陆状态。
解决办法:强制把JSESSIONID传递给相关资源
Java Servlet API 中提出了跟踪Session的另一种机制,如果客户端浏览器不支持Cookie,容器可以重写客户请求的URL,把JSESSIONID添加到 URL信息中。HttpServletResponse接口提供了重写 URL 的方法:public String encodeURL(String url)
- 先判断当前的Web组件是否启用Session,如果没有启用Session,直接返回参数url
- 如果启用Session,再判断客户端浏览器是否支持Cookie
- 如果支持Cookie,直接返回参数url
- 如果不支持Cookie,就在参数url中加入JSESSIONID信息,然后返回修改后的url
如点击以下链接:
<a href = <%=response.encodeURL("admin/doServlet")%> >URL重写访问</a>
4、Cookie和Session的区别
- 都是保存用户信息,不同在于Session存储在服务器端,Cookie是存储在客户端
- Session中可以保存任意对象,Cookie只能保存字符串
- Session随会话结束而关闭,Cookie可以长期保存在客户端硬盘上,也可以临时保存在浏览器内存中
- Session用来保存重要信息,Cookie用来保存不重要的用户信息