JSP基础(八)——使用Cookie记录信息

来源:互联网 发布:a站程序员 编辑:程序博客网 时间:2024/05/16 07:42

    Cookie是一种应用很久的技术了,早在Html刚刚出现的时候,在每个独立的页面之间没有办法记录和标识不同的用户,后来人们就发明了Cookie技术,当用户访问网页时,它能够在访问者的机器(硬盘)上创立一个文件,我们把它叫做Cookie,写一段内容进去,来标志不同的用户。如果下次用户再访问这个网页的时候,它又能够读出这个文件里面的内容,这样的网页就知道上次这个用户已经访问过该网页了。

一、Cookie的概念和特性

1.1 什么是Cookie

    Cookie是服务器发给浏览器的体积非常小的纯文本信息,用户以后访问同一个Web服务器时,浏览器会把它们原样发送给服务器。通过让服务器读取它原先保存到客户端的信息,网站能够为浏览者提供一系列的方便。

    Cookie数据存储的功能由浏览器提供,因此,Cookie功能都必须要有浏览器的支持,一般通用的浏览器都支持此功能。

    当用户打开的网页中包含Cookie程序代码时,服务器端会建立Cookie数据,然后将这个Cookie传送到客户端用户的计算机上。Cookie示意图如下:


    当Cookie的数据传送至客户端的计算机之后,边存储在浏览器当中,此时服务器端的网页都可以访问这个Cookie的数据内容,而当用户关闭浏览器的时候,Cookie的数据便会消失。

    若服务器在建立Cookie时设置了Cookie的存在时间期限,则用户在关闭浏览器之后,Cookie的数据会以文本文件存储在用户的计算机上,只要在设置的时间期限内,当用户连接网页时,服务器端的网页均可使用先前Cookie的内容,等到了所设置的期限后,Cookie中的数据便会自动被删除。


1.2 Cookie的常见用途

(1)网站浏览人数管理

(2)按照用户的喜好定制网页的外观

(3)在电子商务站点中实现诸如“购物车”等功能


1.3 对Cookie进行适当设置

    在IE浏览器,对Cookie进行适当设置:



   在打开的“Internet选项”对话框中选择“隐私”选项卡(有的IE版本可以在“安全”选项卡中单击“自定义级别”按钮进行简单调整),调整Cookie的安全级别,通常情况下,可以将滑块滑至“中高”或者“高”的位置。

    多数论坛站点需要使用Cookie信息,如果用户从来不去这些地方,可以将安全级别调制“阻止所有Cookie”即“高”。如果只是为了阻止个别网站的Cookie,可以单击“高级”按钮,在打开的“高级隐私策略设置”的对话中,可以对第一方Cookie和第三方Cookie进行设置。(第一方Cookie是用户正在浏览的网站的Cookie,第三方是非正在浏览的网站发给用户的Cookie),通常要对第三方Cookie选择“阻止”。

   


    如果需要保存Cookie,可以使用IE的“导入和导出”功能,选择“文件"|“导入和导出”命令,打开“导入和导出向导”对话框,按提示操作即可。



    如果想查看所有保存到用户电脑里的Cookie,可以在”Internet选项“的“常规”选项卡中,单击“设置”,在打开的“设置”对话框中单击“查看文件”按钮,在打开的Temporary Internet Files窗口中查看文件,这些文件通常是以user@domain格式命名的(user是用户本地用户名,domain是所访问的网站的域名)。


(Cookie中的内容大多数经过了加密处理,因此在用户看来只是一些毫无意义的字母和数字组合,只有服务器的CGI处理程序才知道他们真正的含义。)


    如果想从IE中删除Cookie文件,可以按照以下步骤删除存储在计算机上的Cookie。删除Cookie之后,网站将不在记住用户以前访问时所输入的信息。例如,网站将不再保存用户的用户名或首选项记录)。

    选择“开始”|”控制面板”,然后单击“Internet选项”,打开“Internet属性”;选择“常规”选项卡,然后在“浏览历史记录”选项组中单击“删除”按钮,在弹出的“删除浏览的历史记录”对话框中勾选上需要删除的点击“删除”即可。





二、在JSP中使用Cookie

    Cookie实质上是服务器端与客户端之间传送的普通http头,可以保存也可以不保存在用户的硬盘上,如果保存,是每个不超过4KB的文本文件,多个Cookie可保存到同一个文件中。如果从编程角度看,在JSP中的Cookie就是Java提供的一个类。

  

2.1 创建Cookie

     Cookie是由javax.servlet.http.Cookie类所衍生出来的对象,建立Cookie的语法如下:Cookie objCookie = new Cookie(indexValue,stringValue);

    由此可见,一个Cookie对象必须包含一个特定的indexValue索引值字符串类型的数据内容stringValue

     建立了Cookie之后,该Cookie数据还必须传送到客户端,用addCookie()方法发送一个HTTP Header。传送方式为response.addCookie(objCookie);

    response对象和request对象均提供与Cookie相关的方法成员,利用这些成员,用户可以很轻易地访问指定的Cookie内容。上述程序片段利用response的addCookie()方法将指定的Cookie对象传送至客户端。


2.2 读写Cookie

2.2.1 写Cookie

    对Cookie进行操作首先是将Cookie保存到客户端。在JSP编程中,利用response对象通过addCookie()方法将Cookie写入客户端,语法格式为:response.addCookie(objCookie);

例如:

<%  //从提交的HTML表单中获取用户名    String username = request.getParameter(name);    Cookie user_name = new Cookie("cookie_name",username); //创建了一个Cookie    response.addCookie(user_name);%>


2.2.2  读Cookie

    将Cookie保存到客户端,就是为了以后得到其中保存的数据。调用HttpServletRequest的getCookies,得到一个Cookie对象的数组。其语法格式如下: Cookie[] arrayName = request.getCookies();

    在客户端传来的Cookie数据类型都是数组类型,因此要得到其中某一指定的Cookie对象,需要遍历数组来找。JSP将调用request.getCookies()从客户端读入Cookie,getCookies()方法返回一个HTTP请求头中的内容对应的Cookie对象数组。用户只需用循环访问该数组的各个元素,调用getName()方法检查各个Cookie的名字,直至找到目标Cookie,然后对该Cookie调用getValue()方法取得与指定名字相关联的值。可通过如下代码实现:

<%    Cookie[] Cookies = request.getCookies(); //创建一个Cookie对象数组    if(Cookies == null) {    out.print("none any Cookie");    }else{    for(int i=0; i<Cookies.length;i++) {//设立一个循环,来访问Cookie对象数组的每一个元素        if(Cookies[i].getName().equals("cookie_name")) {  //判断元素的值是否为username中的值    out.println(Cookies[i].getValue()+"<br>");        }    }      }%>


2.3 Cookie中的主要方法

    在JSP中,通过Cookie.set***来设置各种属性,用Cookie.get***读出Cookie的属性,Cookie的主要属性如下表:

Cookie中的主要方法及其说明类型方法名方法解释StringgetComment()返回Cookie中的注释,没有注释就返回空值StringgetDomain()返回Cookie中Cookie适用的域名。使用getDomain()方法能指示浏览器把Cookie返回给同一域内的其他服务器,而通常Cookie只返回给和发送它的服务器名字完全相同的服务器。intgetMaxAge()返回Cookie过期之前的最大时间,以秒计算StringgetName()返回Cookie的名字。名字和值始终是我们关心的两个部分。StringgetPath()返回Cookie适用路径。如果不指定路径,Cookie将返回给当前页面所在目录及其子目录下的所有页面。booleangetSecure()如果浏览器通过安全协议发送Cookie,将返回true值,如果浏览器使用标准协议,则返回falseStringgetValue()返回Cookie的值intgetVersion()返回Cookie所遵从的协议版本voidsetCommon(String purpose)设置Cookie中的注释voidsetDomain(String pattern)设置Cookie中Cookie适用的域名voidsetMaxAge(int expiry)设置Cookie过期时间,以秒计算voidsetPath(String uri)设置能够访问Cookie对象的网页路径为uri与其下的子目录voidsetSecure(boolean flag)指出浏览器使用的安全协议,例如HTTPS或SSLvoidsetValue(String newValue)Cookie创建后设置一个新的值voidsetVertion(int v)设置Cookie所遵从的协议版本

2.4 几个操纵Cookie的常用方法

2.4.1设置Cookie的存在期限

    Cookie在生成时,会指定一个Expire值,这就是Cookie的生存周期,在这个周期内Cookie有效,超出周期Cookie就会被清除。有些页面将Cookie的生存周期设置为0或者负值,这样在关闭Cookie时,就会马上清除Cookie,不会记录用户信息,更加安全。  在默认情况下,Cookie是随着用户关闭浏览器而自动消失的,不过,Cookie也可以设置其存在的期限,让用户在下次打开网页时,服务器端仍能取得同一个Cookie中的数据内容。

    例:使用setMaxAge()方法设置Cookie对象login在一个小时之内是有效的:

<%    Cookie login = new Cookie("today","true");    login.setMaxAge(3600);    response.addCookie(login);%>

    如果希望Cookie能够在浏览器退出时自动保存下来,则可以用下面的LongLivedCookie类来取代标准的LongLivedCookie类。LongLivedCookie类代码如下:

import javax.servlet.http.*;public class LongLivedCookie extends Cookie{public  static final int SECONDS_PER_YEAR = 60*60*24*365;public LongLivedCookie(String name,String value) {super(name,value);setMaxAge(SECONDS_PER_YEAR);}}

2.4.2 删除Cookie

    要删除某一个客户端的Cookie,必须使用前面的setMaxAge()方法,并将Cookie的存在期限设置为0,方式为:Cookie cookieName.setMaxAge(0);

    例:下面的代码为在JSP中删除一个Cookie:

<%    Cookie killMyCookie = new Cookie("myCookie",null);    killMyCookie.setMaxAge(0);    killMyCookie.setPath("/");    response.addCookie(killMyCookie);%>

2.4.3 获取指定名字的Cookie的值

例:获取指定名字的Cookie值:

public static String getCookieValue(Cookie[] cookies,String cookieName,String defaultValue) {for(int i=0;i<cookies.length;i++) {    Cookie cookie = cookies[i];    if(cookieName.equals(cookie.getName())) { return(cookie.getValue());    }}return defaultValue; }




三、Cookie对象的应用实例

例1:在JSP中使用Cookie,其中writeCookie.jsp用于写入Cookie,readCookie.jsp用于读取Cookie。

writeCookie.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>writeCookie</title></head><body><h2>操纵Cookie示例--写入</h2><%   try{   Cookie _Cookie = new Cookie("myCookie","COOKIE_TEST");   _Cookie.setMaxAge(10*60);    //设置Cookie存活时间为10分钟   response.addCookie(_Cookie);   out.println("已把Cookie写入客户端了!!!");   }catch(Exception e) {   System.out.println(e);   }%></body></html>

readCookie.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>readCookie</title></head><body><h2>操作Cookie示例--读取Cookie</h2><%    //将当前站点的所有Cookie读入并存入Cookie数组中    Cookie[] Cookies = request.getCookies();    Cookie sCookie = null;    String cookieName = null;    String cookieValue = null;    if(Cookies == null) {    out.print("没有Cookie!!!");    }else {    try{    if(Cookies.length == 0) {    System.out.print("客户端禁止写入Cookie!");    }else {    for(int i=0; i<Cookies.length; i++) {    sCookie = Cookies[i];    cookieName = sCookie.getName();    cookieValue = sCookie.getValue();    if(cookieName.equals("myCookie")) {    out.println(cookieName+"->"+cookieValue+"<br>");    break;    }    }    }    }catch(Exception e){    System.out.println(e);    }    }%></body></html>
    readCookie.jsp必须注意两个问题:一是读入Cookie数组时需要判断是否为null,如果为null,就不能进行下一步操作,只能显示出Cookie为空的错误信息。二是对Cookie的长度进行判断,如果Cookie.length==0,说明客户端浏览器不支持Cookie。


    直接执行readCookie.jsp,此时的Cookie为null :


    执行writeCookie.jsp之后(10分钟之内),再执行readCookie.jsp:

 


例2 本例中CookieJSP.jsp创建并保存Cookie,showCookie.jsp取得客户端所有Cookie信息,并在页面上显示。

CookieJSP.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>CookieJSP</title></head><body><h2>操纵Cookie示例--CookieJSP</h2><%    String name = (request.getParameter("name")!=null)?request.getParameter("name"):"Jack";//取得传入名字参数    Cookie cookie = new Cookie("name",name);//创建Cookie    cookie.setMaxAge(600); //设置Cookie保存时间为10分钟    response.addCookie(cookie); //在客户端保存Cookie%><a href="showCookie.jsp">显示Cookie值</a></body></html>

showCookie.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>showCookie</title></head><body><h2>Cookie如下所示:</h2><%    //取得客户端的所有Cookie    Cookie[] Cookies = request.getCookies();    Cookie sCookie = null;    String cookieName = null;    String cookieValue = null;    int cookieVersion = 0;    if(Cookies == null) {//如果没有任何Cookie    out.println("没有Cookie!!!");    }else {    try{    if(Cookies.length == 0) {    System.out.println("客户端禁止写入Cookie!");    } else {    for(int i=0; i<Cookies.length; i++) {    sCookie = Cookies[i];    cookieName = sCookie.getName();    cookieValue = sCookie.getValue();    cookieVersion = sCookie.getVersion();    out.print("<p><b>Cookie的名字是:"+cookieName+"</b></p><br>");    out.print("<p><b>Cookie的版本是:"+cookieVersion+"</b></p><br>");    out.print("<p><b>Cookie的值是:"+cookieValue+"</b></p><br>");        }            }            }catch(Exception e) {    System.out.println(e);    }    }%></body></html>

直接执行CookieJSP.jsp,然后点击超链接

   


  

    从上述运行结果可见,同一台机器的不同客户端都可以访问服务器保存在本地的Cookie。新开启的页面中没有保存JSESSIONID的信息。

    jsessionid就是客户端用来保存sessionid的变量,一般对于Web应用来说,客户端变量都会保存在Cookie中,jsessionid也不例外。不过与一般的Cookie变量不同的是,jesessionid是保存在内存Cookie中,在一边Cookie文件中看不到。

    注:内存Cookie在打开一个浏览器窗口的时候会创建,在关闭这个浏览器窗口也会同时销毁。这也就解释了为什么session变量为什么不能跨窗口使用,要胯窗口就要手动把jsessionid手动保存到Cookie中的问题。

    只有通过jsessionid才能使session机制起作用,而jsessionid又是通过Cookie来保存的。如果用户禁用了Cookie,可以通过URL重写来实现jesessionid的传递。jesessionid通过这样的方式来从客户端传递到服务器端,从而来标识session。这样用户禁用Cookie时,也可以传递jsessionid使用session,只不过每次都把jsessionid作为参数跟在url后面传递,想想都觉得很麻烦!

    不过sun提供了两个方法使事情变得简单:response.encodeURL()response.encodeRedirectURL()。这两个方法会判断Cookie是否可用,如果禁用了,会解析出url中的jsessionid,并连接到指定的url后面;如果没有找到,jsessionid会自动帮我们生成一个。(在调用response.sendRedirect()之前,应先调用response.encodeURL()或encodeRedirectURL()方法,否则可能会丢失session。)

例3 服务器使用URL重写,jsessionid1.jsp利用response对象内的encodeURL方法,将URL做了一个编码动作。 jsessionid2.jsp显示sessionID

jsessionid1.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><%    String url = response.encodeURL("jsessionid2.jsp");    response.sendRedirect(url);%>

jsessionid2.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><% out.println("sessionID is "+session.getId()); %>

运行结果:




四、Cookie的安全问题

      由于浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB,因此Cookie不会塞满用户的硬盘,更不会被用作“拒绝服务”的攻击手段。


4.1 Cookie欺骗

    Cookie记录着用户的账户ID、密码之类的信息,如果在网上传递,通常使用的是MD5的传递方式,即使被截获,也看不懂,然而截获这些字符串不需要知道它们的意义,他们只需要把别人的Cookie向服务器提交,并且能够通过验证,这样就可以冒充受害人的身份登录网站,这种方法叫做Cookie欺骗。

    目前,网站的验证程序要排除所有的非法登录是十分困难的,也没有防范的特效药,用户只能使用通常的防护方法,不要在论坛里使用重要的密码,也不要使用IE自动保存密码的功能,以及尽量不要登录不了解底细的网站。


4.2 Flash的代码隐患

    Flash可以利用它的getURL()函数自动打开指定的网页,因此他可能把用户引向一个包含恶意代码的网站。对于Flash的这种行为,网站是无法禁止的,因为这是Flash文件的内部行为。用户所能做到的,如果是本地浏览尽量打开防火墙,如果防火墙提示的向外发送的数据包并不知悉,最好禁止。如果是在Internet上欣赏,最好找一些知名的大网站。


4.3 隐私、安全和广告

     Cookie在某种程度上说已经危及用户的隐私和安全。其中有一种是:访问了一些从未去过的网站(通过搜索引擎),而这些网站包含了一种“网络臭虫”的图片,该图片透明,且只有一个像素大小(以便隐藏),它们的作用是将所有访问过此页面的计算机写入Cookie,而后,电子商务网站将读取这些Cookie信息,并寻找写入这些Cookie的网站,随即发送包含这个网站的相关产品广告的垃圾邮件给访问者。

     因为更具有针对性,使这套系统行之有效,收到邮件的访问者或多或少表现出对产品的兴趣,这些站点一旦写入Cookie并使其运作,就可以从电子商务网站那里获取报酬,以维持网站的生存。