Cookie与Session简介
Cookie与Session简介
本章介绍重点:
本章重点为大家介绍在Web开发过程当中经常会使用到的Cookie与Session的概念,它们的使用方法和应用场景,以及它们的优点与局限等等。深刻理解与掌握它们的用法,可以更好的帮助我们开发出正确可用的产品。
我们为什么需要Cookie与Session:
在开始本章程的介绍之前,我们有必要要问自己一个问题,我们为什么需要Cookie与Session?它们可以帮助我们解决什么问题?
让我们先来了解了解我们经常使用的HTTP协议是什么:HTTP是一个属于应用层的面相对象的应用协议,它具有以下五个特点:
- 支持客户端<->服务器服务
- 简单快速
- 灵活
- 无连接
- 无状态
如何理解HTTP的无状态特性?用当下流行的一句话来描述就是“人生若只如初见”。HTTP协议处理事务请求没有记忆能力,对同一个URL的请求没有上下文的关系,你所发出的每一次HTTP请求都是独立的,它的执行情况与响应的结果不会受到之前的HTTP请求的影响,当然它也不会干扰影响后续的HTTP请求与响应,处理HTTP请求的服务器没有保存客户端的状态。
可以设想一下,假如基于这些特性而不做任何的特殊处理与改进,我们访问网络站点时会是怎样的体验?拿网购来说吧。当我们访问某电子商城的时候,提示需要输入用户名以及密码,我们按要求填写所需信息成功登陆,琳琅满目的商品展示在我们的眼前,我看上了一款最新的电子产品,打算点进去看看详细介绍,可接下的情况却让我们大跌眼镜,由于服务器没有我们的登陆状态,网站竟要求我重新输入用户名跟密码?这将会是一个多么糟糕的用户体验。
很明显,HTTP的这种无状态的特性严重的阻碍了我们与服务器的交互,于是两种用于保持HTTP连接状态的技术就应用而生了:Cookie与Session,这也是我们本章的介绍重点。
Cookie:
Cookie是什么?
翻阅维基百科以及百度百科,我们不难发现,Cookie 是在 HTTP 协议下,服务器或脚本用以维护客户工作站信息的一种方式。它是由 Web 服务器保存在用户浏览器(客户端)上的小文本文件,可以用于记录用户的活动或者是与记录与状态相关的信息。Cookie是由W3C组织提出,最早由NetScape公司开发实现,现已经成为了一种标准,主流浏览器都支持Cookie机制。
Cookie的工作机制可以参见下面的图示:
正如前面所说,Cookie保存在客户端电脑,不同的浏览器,存放的路径可能有所不同,如下列举几个常见主流浏览器的存放位置:
- IE存放位置:C:\Users\{$UserName}\AppData\Roaming\Microsoft\Windows\Cookies\xxx.txt
- FireFox存放位置:C:\Users\{$UserName}\AppData\Roaming\Mozilla\Firefox\Profiles\{$xxx.default}\cookies.sqlite
- Chrome存放位置:C:\Users\{$UserName}\AppData\Local\Google\Chrome\User Data\Default\Cookies
注意:IE浏览器中,IE将各个站点的Cookie分别保存为一个txt纯文本文件;而Firefox和Chrome是将所有的Cookie都保存在一个文件中,该文件的格式为SQLite3数据库格式的文件。
Cookie的属性:
Cookie的常用属性可以参阅下列表格:
Cookie的Server Side操作:
创建一个新的Cookie,我们可以通过以下的代码来实现:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie myCookie = new Cookie("username", "WebOpenShare");
myCookie.setMaxAge(300);
myCookie.setDomain("www.webopenshare.com");
myCookie.setPath("/");
myCookie.setSecure(false);
response.addCookie(myCookie);
}
运行上述的代码,我们便可以得到一个名为"username",其对应的值为"WepOpenShare"。(如果你是本地运行Tomcat服务器,请记得修改你电脑hosts文件)
Cookie对象没有提供直接修改其属性的方法,要修改原有Cookie的值,我们只能够通过创建同名的Cookie并添加到response中覆盖掉原Cookie的设置,如下所示:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // ... Cookie myModifiedCookie = new Cookie("username", "MyWebOpenShare"); myModifiedCookie.setMaxAge(600); myModifiedCookie.setDomain("www.webopenshare.com"); myModifiedCookie.setPath("/"); myModifiedCookie.setSecure(false); response.addCookie(myModifiedCookie); }
同样的,Cookie对象也没有提供直接删除某一个Cookie的操作方法,想要删除某一个Cookie,我们只能够通过新建一个maxAge为0的同名Cookie,把它添加到response中删除原先的Cookie,具体如下代码所示:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // ... Cookie deleted = new Cookie("username", "MyWebOpenShare"); deleted.setMaxAge(0); deleted.setDomain("www.webopenshare.com"); deleted.setPath("/"); deleted.setSecure(false); response.addCookie(deleted); }
注意:修改跟删除某一个Cookie时,我们要通过创建一个同名Cookie来进行覆盖,对于这一个同名Cookie,除了它的value跟maxAge属性可以不同,其余的所有属性必须跟要修改的Cookie保持一致,否则将会操作失败。
Cookie的Client Side操作:
我们知道Cookie是保存在客户端的,那么我们可不可以通过一些脚本语言,例如JavaScript在浏览器中操作Cookie呢?如果有,我们可不可以像在Server Side操作Cookie一样,对Cookie进行读写/修改甚至是删除的操作呢?
可以肯定的是,我们可以通过脚本在浏览器中操作Cookie,但是出于安全性的考虑,它所允许的操作非常有限,仅限于读取当前域名下的Cookie,不可以修改或者删除Cookie。通过下面的代码我们就可以读取出当前Domain下的Cookies.
<script>document.write(document.cookie);</script>
Cookie应该存放什么值:
前面的介绍当中,我们提及Cookie存放在客户端的文件上,如果客户端被入侵,那么这些Cookie文件存在被盗的潜在危险;另一方面,我们都知道,HTTP协议采用的是明文传输的方式,如果有人监听或者是截取了我们的请求,那么我们通过Cookie传送给服务器的信息就就全部曝露在入侵者面前。因此,存放在Cookie里面的值应当尽量避免个人敏感信息,如果非要存放敏感关键信息的时候,也要先经过加密处理之后再存放。
Session:
Session是什么?
Session是另外一种用户保持HTTP连接状态的解决方案,与Cookie不同,Session存放于服务器内存当中,服务器采用了一种类似于散列表(Hashtable)的形式来存放Session对象信息。
Session保存在服务器上,所以它会消耗服务器的资源,因此,我们不应该在Session里面存放太多太过复杂厚重的对象跟信息,在高并发的情况之下,这样做很容易会使得服务器内存溢出使得程序异常或者最终宕机。
Session的机制:
Session的机制,可以参见下图:
Session何时创建?
Session何时被创建呢?是不是我们访问服务器就会创建一个Session呢?答案是否定的,只有我们在程序中调用到Session的时候,服务器才会帮我们创建Session对象。例如在Servlet当中,当我们调用request.getSession()的方法时,服务器就会创建一个Session对象。但是细心的朋友可能会发现,当我访问某一个JSP页面的时候,也会有Session对象生成,此时我并没有在Servlet或者是JSP当中显式的使用任何的request.getSession()方法。这里我特别强调的是显式这个词语,其实当我们访问JSP的时候,JSP编译成Servlet的时候默认会帮我们添加这样的代码:HttpSession session = request.getSession(),这也是为什么我们可以什么都不做,就直接在JSP页面当中使用session.getAttribute()或者是其它的操作。
Session何时销毁?
前面谈了Session的创建,接下来我们来看看Session何时被销毁?当然,关闭服务器可以保证所有的Session被销毁。那关闭浏览器呢?很多人有一个误解,觉得只要我关闭了浏览器,Session就销毁了。其实这种理解是不全面的,我们知道,Session是由服务器创建并维护的,因此销毁与否须由服务器来完成,单纯关闭端浏览器并不会触发销毁内存的动作,如果我们重新打开浏览器,并向服务器发送之前的Session ID,是可以找回之前的Session的。只有在关闭浏览器的同时触发一条服务器请求,告诉服务器销毁掉内存,那才可以做到这样的效果。
恰恰是由于关闭浏览器并不能销毁内存,出于安全性的考量,我们需要为Session来设置一个有效期,当一次访问距离上次的请求超过这个有效期的话,那之前的Session就会销毁失效。
Cookie被禁用时?
Session的工作机制,默认情况下是需要浏览器的Cookie来配合工作的。当服务器创建一个全新的Session之后,会向浏览器发送一个Session ID的信息,通常是以Cookie的形式返回给客户端,在接下来的请求中,客户端便会自动在请求当中携带上这个Session ID的参数,服务器根据传递上来的Session ID直接从服务器中查找返回之前的Session对象。但是如果客户端禁用Cookie呢?
由于Cookie可以被人为的禁止,必须有其它机制以便在Cookie被禁止时仍然能够把Session ID传递回服务器。经常被使用的一种技术叫做URL重写,就是把Session ID直接附加在URL路径的后面,附加方式也有两种,一种是作为URL路径的附加信息,表现形式为http://${domain}:${port}/${uri};SESSIONID=xxxxxxxxxxx;另一种是作为查询字符串附加在URL后面,表现形式为http://${domain}:${port}/${uri}?SESSIONID=xxxxxxxxxxx。
Session常用方法:
Session的常用方法总结如下表所示:
抛出引子:
部署在同一服务器上的所有应用之间是不是共享同一个Session?请关注我们,在后续章节跨应用Session共享中我们会为您揭秘。
我要小额赞助,鼓励作者写出更好的文章:
posted on 2018-03-02 17:07 WebOpenShare 阅读(352) 评论(0) 编辑 收藏 举报