`
shenzhw
  • 浏览: 62035 次
  • 性别: Icon_minigender_1
  • 来自: 福州
文章分类
社区版块
存档分类
最新评论
阅读更多

cookie概述【转】 并修改
  假如利用一个不变的框架来存储购物栏数据,而商品显示页面是不断变化的,尽管这样能达到一个模拟全局变量的功能,但并不严谨。例如在导航框架页面内右击,单击快捷菜单中的【刷新】命令,则所有的JavaScript变量都会丢失。因此,要实现严格的跨页面全局变量,这种方式是不行的, JavaScript中的另一个机制:cookie,则可以达到真正全局变量的要求。
  cookie 是浏览器提供的一种机制,它将document对象的cookie属性提供给JavaScript。可以由JavaScript对其进行控制,而并不是 JavaScript本身的性质。cookie是存于用户硬盘的一个文件,这个文件通常对应于一个域名,当浏览器再次访问这个域名时,便使这个 cookie可用。因此,cookie可以跨越一个域名下的多个网页,但不能跨越多个域名使用。
  不同的浏览器对cookie的实现也不一样,但其性质是相同的。例如在Windows 2000以及Windows xp中,IE的cookie文件存储于documents and settings\userName\cookie\文件夹下。通常的命名格式为:userName@domain.txt。Chrome的Cookie文件存储在C:\Documents and Settings\Administrator\Local Settings\Application Data\Google\Chrome\User Data\Default中的Cookie文件中。
  cookie机制将信息存储于用户硬盘,因此可以作为全局变量,这是它最大的一个优点。它可以用于以下几种场合。
1.保存用户登录状态。例如将用户id存储于一个cookie内,这样当用户下次访问该页面时就不需要重新登录了,现在很多论坛和社区都提供这样的功能。cookie还可以设置过期时间,当超过时间期限后,cookie就会自动消失。因此,系统往往可以提示用户保持登录状态的时间:常见选项有一个月、三个月、一年等。
2.跟踪用户行为。例如一个天气预报网站,能够根据用户选择的地区显示当地的天气情况。如果每次都需要选择所在地是烦琐的,当利用了cookie后就会显得很人性化了,系统能够记住上一次访问的地区,当下次再打开该页面时,它就会自动显示上次用户所在地区的天气情况。因为一切都是在后台完成,所以这样的页面就像为某个用户所定制的一样,使用起来非常方便。
3.定制页面。如果网站提供了换肤或更换布局的功能,那么可以使用cookie来记录用户的选项,例如:背景色、分辨率等。当用户下次访问时,仍然可以保存上一次访问的界面风格。
4.创建购物车。正如在前面的例子中使用cookie来记录用户需要购买的商品一样,在结账的时候可以统一提交。例如淘宝网就使用cookie记录了用户曾经浏览过的商品,方便随时进行比较。
当然,上述应用仅仅是cookie能完成的部分应用,还有更多的功能需要全局变量。cookie的缺点主要集中于安全性和隐私保护。主要包括以下几种:
1.cookie可能被禁用。当用户非常注重个人隐私保护时,他很可能禁用浏览器的cookie功能;
2.cookie是与浏览器相关的。这意味着即使访问的是同一个页面,不同浏览器之间所保存的cookie也是不能互相访问的;
3.cookie可能被删除。因为每个cookie都是硬盘上的一个文件,因此很有可能被用户删除;
4.cookie安全性不够高。所有的cookie都是以纯文本的形式记录于文件中,因此如果要保存用户名密码等信息时,最好事先经过加密处理。
设置cookie
每个cookie都是一个名/值对,可以把下面这样一个字符串赋值给document.cookie:
document.cookie=”userId=828″;
如果要一次存储多个名/值对,可以使用分号加空格(; )隔开,例如:
document.cookie=”userId=828; userName=hulk”;
在cookie 的名或值中不能使用分号(;)、逗号(,)、等号(=)以及空格。在cookie的名中做到这点很容易,但要保存的值是不确定的。如何来存储这些值呢?方法是用escape()函数进行编码,它能将一些特殊符号使用十六进制表示,例如空格将会编码为“20%”,从而可以存储于cookie值中,而且使用此种方案还可以避免中文乱码的出现。例如:
document.cookie=”str=”+escape(”I love ajax”);
相当于:
document.cookie=”str=I%20love%20ajax”;
当使用escape()编码后,在取出值以后需要使用unescape()进行解码才能得到原来的cookie值,这在前面已经介绍过。
尽管document.cookie看上去就像一个属性,可以赋不同的值。但它和一般的属性不一样,改变它的赋值并不意味着丢失原来的值,例如连续执行下面两条语句:
document.cookie=”userId=828″;
document.cookie=”userName=hulk”;
这时浏览器将维护两个cookie,分别是userId和userName,因此给document.cookie赋值更像执行类似这样的语句:
document.addCookie(”userId=828″);
document.addCookie(”userName=hulk”);
事实上,浏览器就是按照这样的方式来设置cookie的,如果要改变一个cookie的值,只需重新赋值,例如:
document.cookie=”userId=929″;
这样就将名为userId的cookie值设置为了929。
获取cookie的值
下面介绍如何获取cookie的值。cookie的值可以由document.cookie直接获得:
var strCookie=document.cookie;
这将获得以分号隔开的多个名/值对所组成的字符串,这些名/值对包括了该域名下的所有cookie。
在实际开发中,cookie常常需要长期保存,例如保存用户登录的状态。这可以用下面的选项来实现:
document.cookie=”userId=828; expires=GMT_String”;
其中GMT_String是以GMT格式表示的时间字符串,这条语句就是将userId这个cookie设置为GMT_String表示的过期时间,超过这个时间,cookie将消失,不可访问。
删除cookie
为了删除一个cookie,可以将其过期时间设定为一个过去的时间.
指定可访问cookie的路径
默认情况下,如果在某个页面创建了一个cookie,那么该页面所在目录中的其他页面也可以访问该cookie。如果这个目录下还有子目录,则在子目录中也可以访问。例如在 www.xxxx.com/html/a.html 中所创建的cookie,可以被  www.xxxx.com/html/b.html 或 www.xxx.com/html/ some/c.html 所访问,但不能被 www.xxxx.com/d.html 访问。
为了控制cookie可以访问的目录,需要使用path参数设置cookie,语法如下:
document.cookie=”name=value; path=cookieDir”;
其中cookieDir表示可访问cookie的目录。例如:
document.cookie=”userId=320; path=/shop”;
就表示当前cookie仅能在shop目录下使用。
如果要使cookie在整个网站下可用,可以将cookie_dir指定为根目录,例如:
document.cookie=”userId=320; path=/”;
指定可访问cookie的主机名
和路径类似,主机名是指同一个域下的不同主机,例如:
www.google.com 和 gmail.google.com就是两个不同的主机名。默认情况下,一个主机中创建的cookie在另一个主机下是不能被访问的,但可以通过domain参数来实现对其的控制,其语法格式为:
document.cookie=”name=value; domain=cookieDomain”;
以google为例,要实现跨主机访问,可以写为:
document.cookie=”name=value;domain=.google.com”;
这样,所有google.com下的主机都可以访问该cookie。
综合示例:构造通用的cookie处理函数
cookie的处理过程比较复杂,并具有一定的相似性。因此可以定义几个函数来完成cookie的通用操作,从而实现代码的复用。下面列出了常用的cookie操作及其函数实现。
1.设置COOKIE
function SetCookie(name,value,expires,path,domain,secure)
{
var expDays = expires*24*60*60*1000;
var expDate = new Date();
expDate.setTime(expDate.getTime()+expDays);
var expString = ((expires==null) ? “” : (”;expires=”+expDate.toGMTString()))
var pathString = ((path==null) ? “” : (”;path=”+path))
var domainString = ((domain==null) ? “” : (”;domain=”+domain))
var secureString = ((secure==true) ? “;secure” : “” )
document.cookie = name + “=” + escape(value) + expString + pathString + domainString + secureString;
}
2.获取指定名称的cookie值:
function GetCookie(name)
{
var result = null;
var myCookie = document.cookie + “;”;
var searchName = name + “=”;
var startOfCookie = myCookie.indexOf(searchName);
var endOfCookie;
if (startOfCookie != -1)
{
startOfCookie += searchName.length;
endOfCookie = myCookie.indexOf(”;”,startOfCookie);
result = unescape(myCookie.substring(startOfCookie, endOfCookie));
}
return result;
}
3.删除指定名称的cookie:
function ClearCookie(name)
{
var ThreeDays=3*24*60*60*1000;
var expDate = new Date();
expDate.setTime(expDate.getTime()-ThreeDays);
document.cookie=name+”=;expires=”+expDate.toGMTString();
}

 

深入理解Servlet/JSP之“Cookie和Session原理” 

时间2008-8-5:   作者 李翊  

  作者: 李翊,JAVA高级软件工程师就业班特聘讲师  blog:  (http://blog.sina.com.cn/avaj)  
作者介绍:北京航空航天大学软件工程硕士。原IBM中国研究中心(IBM China Lab)资深系统架构师,是目前国内最著名的企业级应用设计及实现专家之一。曾经负责过的主要项目包括:Petri网实验模型系统、多个省级考试中心信息系统、河南省省级电信计费系统、国务院办公厅信息系统、企业基础信息交换平台、国产信息交换平台集成测试系统、多个基于WBI企业EAI解决方案、ePod企业级电子商务解决方案、电子政务目录交换系统等 . 

由于HTTP协议的无状态特征,Web应用中经常使用Cookie和Session来保存用户在与系统交互过程中的状态数据。下面通过分析HTTP协议对Cookie和Session的工作原理加以了解。 
一、Cookie 
Cookie的含义是“服务器送给浏览器的甜点”,即服务器在响应请求时可以将一些数据以“键-值”对的形式通过响应信息保存在客户端。当浏览器再次访问相同的应用时,会将原先的Cookie通过请求信息带到服务器端。 
下面的Servlet展示了Cookie的功能。 
  ... ... ... 
  public void doGet(HttpServletRequest request, HttpServletResponse response) 
                 throws ServletException, IOException { 
      response.setContentType("text/html"); 
      PrintWriter out = response.getWriter(); 
      String option = request.getParameter("option"); 
      if ("show".equals(option)) { 
          //获得请求信息中的Cookie数据 
          Cookie[] cookies = request.getCookies(); 
          if (cookies != null) { 
              //找出名称(键)为“cool”的Cookie 
              for (int i = 0; i < cookies.length; i++) { 
                  if ("cool".equals(cookies[i].getName())) { 
                      out.println("<h2>" + cookies[i].getName() + ":" 
                          + cookies[i].getValue() + "</h2>"); 
                   } 
              } 
         } 
      } else if ("add".equals(option)) { 
          //创建Cookie对象 
          Cookie cookie = new Cookie("cool", "yeah!"); 
          //设置生命周期以秒为单位 
          cookie.setMaxAge(20); 
          //添加Cookie 
          response.addCookie(cookie); 
     } 
   ... ... ... 
该Servlet对应的url-pattern为/testCookie 
当浏览器请求地址“.../tst/testCookie?option=add”时,该Servlet创建一个Cookie对象,存储的键-值对为“cool”-“yeah”。通过response的addCookie方法将该Cookie信息添加到相应信息中。需要注意的是cookie的setMaxAge方法用于设置该cookie生命周期,单位是秒,如果过了这个期间,Cookie将失效。setMaxAge方法的参数如果为负值则表示该Cookie将在浏览器关闭时过期,如果参数为0则表示立刻删除该Cookie。访问该地址,对应的请求和响应的HTTP信息为: 
请求: 
GET /tst/testCookie?option=add HTTP/1.1 
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/x-silverlight, ** 
Accept-Language: zh-cn 
UA-CPU: x86 
Accept-Encoding: gzip, deflate 
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1) 
Host: 192.168.5.100:8080 
Connection: Keep-Alive 
Cookie: cool=yeah! 
响应: 
HTTP/1.1 200 OK 
Server: Apache-Coyote/1.1 
Content-Type: text/html;charset=ISO-8859-1 
Content-Length: 21 
Date: Sun, 29 Jun 2008 06:15:26 GMT 
<h2>cool:yeah!</h2> 
注意,请求协议头中用于携带cookie信息的格式。 

Cookie可以用于保持用户的会话状态,但Cookie信息保存在客户端,存在较大的安全隐患,且一般浏览器对Cookie的数目及数据大小有严格的限制。在Web应用中,一般情况下通过HttpSession对象保持会话状态。 

二、Session 
Session对象的原理在于,服务器可以为客户端创建并维护一个所谓的Session对象,用于存放数据。在创建Session对象的同时,服务器将会为该Session对象产生一个唯一编号,这个编号称之为SessionID,服务器以Cookie的方式将SessionID存放在客户端。当浏览器再次访问该服务器时,会将SessionID作为Cookie信息带到服务器,服务器可以通过该SessionID检索到以前的Session对象,并对其进行访问。需要注意的是,此时的Cookie中仅仅保存了一个SessionID,而相对较多的会话数据保存在服务器端对应的Session对象中,由服务器来统一维护,这样一定程度保证了会话数据安全性,但增加了服务器端的内存开销。 
存放在客户端的用于保存SessionID的Cookie会在浏览器关闭时清除。我们把用户打开一个浏览器访问某个应用开始,到关闭浏览器为止交互过程称为一个“会话”。在一个“会话”过程中,可能会向同一个应用发出了多次请求,这些请求将共享一个Session对象,因为这些请求携带了相同的SessionID信息。 
1. Session工作原理 
下面的Servlet用来演示Session的工作原理: 
... ... ... 
public void doGet(HttpServletRequest request, HttpServletResponse response) 
   throws ServletException, IOException { 
    response.setContentType("text/html"); 
    PrintWriter out = response.getWriter(); 
    String option = request.getParameter("option"); 
    if ("create".equals(option)) { 
        //获得HttpSession对象 
        HttpSession session = request.getSession(); 
        //设置Session对象的最长不活动间隔 
        session.setMaxInactiveInterval(30); 
        //获取Session中的数据 
        List list = (List) session.getAttribute("list"); 
        if (list == null) { 
            list = new ArrayList(); 
            list.add("hey"); 
            //向Session中添加数据 
            session.setAttribute("list", list); 
        } else { 
        list.add("hey"); 
    } 
     out.println(list); 
   }elseif ("invalidate".equals(option)) { 
       HttpSession session = request.getSession(false); 
       if (session != null) { 
       //使Session对象失效 
       session.invalidate(); 
   } 

  ... ... ... 
该Servlet的url-pattern为/testSession。 
当浏览器请求地址“.../tst/testSession?option=create”时,Servlet调用request的getSession方法获得Session对象,如果此时服务器端存在与请求信息中SessionID(作为Cookie信息携带)对应的Session对象,则返回这个Session对象,否则将会创建一个新的Session对象并将其产生的SessionID以Cookie的形式通过响应信息送回。注意,Session对象的setMaxInactiveInterval方法用于设置最长不活动间隔,单位是秒,如果出现在这个的时间段内Session对象没有被存取,则该Session对象将会失效。通常为了保证服务器的性能和出于安全性考虑,这个值要妥善的设置(Tomcat针对Session的MaxInactiveInterval会有默认的设置)。若setMaxInactiveInterval设置为负值,则表示该Session永不过期。另外,Session对象分别通过setAttribute和getAttribute方法存取数据,数据以“名称-对象”对的形式存放。该请求对应的请求和响应的HTTP信息为: 
请求: 
GET /tst/testSession?option=create HTTP/1.1 
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/x-silverlight, ** 
Accept-Language: zh-cn 
UA-CPU: x86 
Accept-Encoding: gzip, deflate 
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1) 
Host: 192.168.5.100:8080 
Connection: Keep-Alive 
Cookie: JSESSIONID=C69B3053C575ECC8C7FCAF7D189A4FD1 

响应 
HTTP/1.1 200 OK 
Server: Apache-Coyote/1.1 
Content-Type: text/html;charset=ISO-8859-1 
Content-Length: 12 
Date: Sun, 29 Jun 2008 07:20:41 GMT 

[hey, hey] 
注意:请求信息中携带的SessionID值与上一次相应的SessionID之一致。另外响应输出的HTML文本中有两个“hey”,这是因为这次请求Servlet往存放在Session中的list对象中又放置了一个String对象。 

当浏览器请求“.../tst/testSession?option=invalidate”时,Servlet会调用Session对象的invalidate方法用于使该Session对象失效。需要注意的是,此时获取Session对象的方法为重载的getSession(boolean b)其中boolean类型的参数表示当前请求没有和服务器端的某个Session对象关联时是创建新的Session(参数为true时)还是返回null(参数为false时)。 

2、关于URL重写 
从上面的介绍可以看出,Session对象的正常使用要依赖于Cookie。如果考虑到客户端浏览器可能出于安全的考虑禁用了Cookie,应该使用URL重写的方式使Session在客户端禁用Cookie的情况下继续生效。 
下面有两个JSP页面:1.jsp中向Session对象中存入了名为“hi”的一个String类型对象。通过超级链接可以链接到2.jsp,在2.jsp中将获取Session中名为“hi”的对象,并显示在页面上。需要注意的是:在1.jsp中超级链接的地址并不是直接写了“2.jsp”而是通过resopnse的encodeURL方法对这个地址进行了处理。 
1.jsp 
<% 
session.setAttribute("hi","Do you work or are you a student?"); 
%> 
<a href="<%=response.encodeURL("2.jsp")%>">2.jsp</a> 

2.jsp 
<%=session.getAttribute("hi")%> 

首先将浏览器的Cookie禁用(注意要重启IE),然后请求1.jsp,响应后点击链接到2.jsp,这个交互过程涉及到两次请求和相应,HTTP信息如下: 

请求1.jsp 
GET /tst/session/1.jsp HTTP/1.1 
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/x-silverlight, ** 
Referer: http://192.168.5.100:8080/tst/session/1.jsp 
Accept-Language: zh-cn 
UA-CPU: x86 
Accept-Encoding: gzip, deflate 
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1) 
Host: 192.168.5.100:8080 
Connection: Keep-Alive 
响应: 
HTTP/1.1 200 OK 
Server: Apache-Coyote/1.1 
Content-Type: text/html;charset=ISO-8859-1 
Content-Length: 33 
Date: Sun, 29 Jun 2008 07:31:36 GMT 
Do you work or are you a student? 
注意:由于Cookie的禁用,这次请求协议头中虽然没有携带SessionID的信息,但SessionID的信息作为请求地址的一部分传到了服务器端,这就是URL重写的意义所在。 
response的encodeURL方法将根据浏览器是否不支持Cookie决定是否将SessionID信息写入链接地址。 

3、Session对象的持久化 
对于一个企业级应用而言,Session对象的管理十分重要。Sessio对象的信息一般情况下置于服务器的内存中,当服务器由于故障重启,或应用重新加载时候,此时的Session信息将全部丢失。为了避免这样的情况,在某些场合可以将服务器的Session数据存放在文件系统或数据库中,这样的操作称为Session对象的持久化。Session对象在持久化时,存放在其中的对象以序列化的形式存放,这就是为什么一般存放在Session中的数据需要实现可序列化接口(java.io.Serializable)的原因了。 
Tomcat 5.5 服务器提供两个类用于Session对象的管理,这两个类分别是org.apache.catalina.session.StandardManager 和 org.apache.catalina.session.PersistentManager。Tomcat默认的方式是使用StandardManager来管理Session。Tomcat 5.5默认会在服务器关闭或应用重新加载时建立一个名为session.ser的文件,并将该应用对应的Session对象存放在其中,该文件位于“Tomcat主目录\work\Catalina\ localhost\应用名”路径下。注意,当Tomcat重新启动或应用重新加载后会读取这个文件,载入其中的Session信息,然后把它删掉,所以如果看不到该文件是由于时机不对或者眼力不够快 。 
当然,可以更改Tomcat默认的Session管理方式。可以在“Tomcat主目录\conf\Catalina”下建立应用对于的Context定义,如建立名为tst.xml的XML文件,文件的内容如下: 
<Context docBase="D:/Tomcat/tomcat-5.5.26/webapps/tst"> 
<Manager className="org.apache.catalina.session.StandardManager" maxActiveSessions="-1"  
    maxInactiveInterval="60" pathname=""/> 
</Context> 
通过Context元素的子元素Manager配置Session的管理对象: 
className属性用于指定管理Session的类可以是StandarManager或PersitentManager。 
maxActiveSessions表示允许最多活动Session对象的数目,-1表示不限制。 
maxInactiveInterval表示Session默认的最长不活动间隔,单位为秒。 
pathname表示StandarManager在服务器重启或应用重新加载时持久化Session对象的文件名,此处设置为“”相当于关掉了Session的持久化机制 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics