认真学了一下cookie的有关内容,在网上看了几篇文章,整理了下,供参考吧.
第一节 cookie 概述
在上一节,曾经利用一个不变的框架来存储购物栏数据,而商品显示页面是不断变化的,尽管这样能达到一个模拟全局变量的功能,但并不严谨。例如在导航框架页面内右击,单击快捷菜单中的【刷新】命令,则所有的 JavaScript 变量都会丢失。因此,要实现严格的跨页面全局变量,这种方式是不行的, JavaScript 中的另一个机制: cookie ,则可以达到真正全局变量的要求。
cookie 是浏览器提供的一种机制 ,它将 document 对象的 cookie 属性提供给 JavaScript 。可以由 JavaScript 对其进行控制,而并不是 JavaScript 本身的性质 。 cookie 是存于用户硬盘的一个文件 ,这个文件通常对应于一个域名 ,当浏览器再次访问这个域名时,便使这个 cookie 可用。因此, cookie 可以跨越一个域名下的多个网页,但不能跨越多个域名使用 。
不同的浏览器对 cookie 的实现也不一样,但其性质是相同的。例如在 Windows 2000 以及 Windows xp 中, cookie 文件存储于 documents and settings\userName\cookie\ 文件夹下。通常的命名格式为: userName@domain.txt 。
cookie 机制将信息存储于用户硬盘,因此可以作为全局变量,这是它最大的一个优点。 它可以用于以下几种场合。
1. 保存用户登录状态 。例如将用户 id 存储于一个 cookie 内,这样当用户下次访问该页面时就不需要重新登录了,现在很多论坛和社区都提供这样的功能。 cookie 还可以设置过期时间,当超过时间期限后, cookie 就会自动消失。因此,系统往往可以提示用户保持登录状态的时间:常见选项有一个月、三个月、一年等。
2. 跟踪用户行为 。例如一个天气预报网站,能够根据用户选择的地区显示当地的天气情况。如果每次都需要选择所在地是烦琐的,当利用了 cookie 后就会显得很人性化了,系统能够记住上一次访问的地区,当下次再打开该页面时,它就会自动显示上次用户所在地区的天气情况。因为一切都是在后台完成,所以这样的页面就像为某个用户所定制的一样,使用起来非常方便。
3. 定制页面 。如果网站提供了换肤或更换布局的功能,那么可以使用 cookie 来记录用户的选项,例如:背景色、分辨率等。当用户下次访问时,仍然可以保存上一次访问的界面风格。
4. 创建购物车 。正如在前面的例子中使用 cookie 来记录用户需要购买的商品一样,在结账的时候可以统一提交。例如淘宝网就使用 cookie 记录了用户曾经浏览过的商品,方便随时进行比较。
当然,上述应用仅仅是 cookie 能完成的部分应用,还有更多的功能需要全局变量。
cookie 的缺点主要集中于安全性和隐私保护。主要包括以下几种:
5. cookie 可能被禁用。当用户非常注重个人隐私保护时,他很可能禁用浏览器的 cookie 功能;
6. cookie 是与浏览器相关的 。这意味着即使访问的是同一个页面,不同浏览器之间所保存的 cookie 也是不能互相访问的;
7. cookie 可能被删除。因为每个 cookie 都是硬盘上的一个文件,因此很有可能被用户删除;
8. cookie 安全性不够高。所有的 cookie 都是以纯文本的形式记录于文件中,因此如果要保存用户名密码等信息时,最好事先经过加密处理。
第二节 cookie 的构成
Cookies 最初设计时,是为了 CGI 编程。但是,我们也可以使用 Javascript 脚本来操纵 cookies 。让我们先来介绍 cookies 的本质。
在 Javascript 脚本里,一个 cookie 实际就是一个字符串属性。当你读取 cookie 的值时,就得到一个字符串,里面当前 WEB 页使用的所有 cookies 的名称和值。每个 cookie 除了 name 名称和 value 值这两个属性以外,还有四个属性。 这些属性是: expires 过期时间、 path 路径、 domain 域、以及 secure 安全。
Expires – 过期时间。 指定 cookie 的生命期。具体是值是过期日期 。如果想让 cookie 的存在期限超过当前浏览器会话时间,就必须使用这个属性 。当过了到期日期时,浏览器就可以删除 cookie 文件 ,没有任何影响。
Path – 路径 。指定与 cookie 关联的 WEB 页。值可以是一个目录,或者是一个路径 。
Domain – 域 。指定关联的 WEB 服务器或域 。 FYI (for your information) :不能把 cookies 域属性设置成与设置它的服务器的所在域不同的值 。
Secure – 安全 。指定 cookie 的值通过网络如何在用户和 WEB 服务器之间传递。这个属性的值或者是 “secure” ,或者为空。缺省情况下,该属性为空,也就是使用不安全的 HTTP 连接传递数据。如果一个 cookie 标记为 secure ,那么,它与 WEB 服务器之间就通过 HTTPS 或者其它安全协议传递数据 。不过,设置了 secure 属性不代表其他人不能看到你机器本地保存的 cookie 。换句话说,把 cookie 设置为 secure ,只保证 cookie 与 WEB 服务器之间的数据传输过程加密,而保存在本地的 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 ,只要建立一个字符串,格式是 name=<value> (名称=值) ,然后把文档的 document.cookie 设置成与它相等即可。比如,假设想保存表单接收到的用户名,那么代码看起来就象这样:
document.cookie = "username" + escape(form.username.value);
设置属性时,不限属性,可以用任何顺序设置 。
获取 cookie 的值
下面介绍如何获取 cookie 的值。 cookie 的值可以由 document.cookie 直接获得:
var strcookie=document.cookie;
这将获得以分号隔开的多个名 / 值对所组成的字符串 ,这些名 / 值对包括了该域名下的所有 cookie 。例如:
<script language="JavaScript" type="text/JavaScript">
<!--
document.cookie="userId=828";
document.cookie="userName=hulk";
var strcookie=document.cookie;
alert(strcookie);
//-->
</script>
图 7.1 显示了输出的 cookie 值。由此可见,只能够一次获取所有的 cookie 值,而不能指定 cookie 名称来获得指定的值,这正是处理 cookie 值最麻烦的一部分 。用户必须自己分析这个字符串,来获取指定的 cookie 值,例如,要获取 userId 的值,可以这样实现:
<script language="JavaScript" type="text/JavaScript">
<!--
// 设置两个 cookie
document.cookie="userId=828";
document.cookie="userName=hulk";
// 获取 cookie 字符串
var strcookie=document.cookie;
// 将多 cookie 切割为多个名 / 值对
var arrcookie=strcookie.split("; ") ;
var userId;
// 遍历 cookie 数组,处理每个 cookie 对
for(var i=0;i<arrcookie.length;i++){
var arr=arrcookie[i].split("=");
// 找到名称为 userId 的 cookie ,并返回它的值
if("userId"==arr[0]){
userId=arr[1];
break;
}
}
alert(userId);
//-->
</script>
这样就得到了单个 cookie 的值
用类似的方法,可以获取一个或多个 cookie 的值,其主要的技巧仍然是字符串和数组的相关操作。
给 cookie 设置终止日期
到现在为止,所有的 cookie 都是单会话 cookie ,即浏览器关闭后这些 cookie 将会丢失,事实上这些 cookie 仅仅是存储在内存中,而没有建立相应的硬盘文件。
在实际开发中, cookie 常常需要长期保存 ,例如保存用户登录的状态。这可以用下面的选项来实现:
document.cookie="userId=828; expires=GMT_String" ;
其中 GMT_String 是以 GMT 格式表示的时间字符串,这条语句就是将 userId 这个 cookie 设置为 GMT_String 表示的过期时间,超过这个时间, cookie 将消失,不可访问。例如:如果要将 cookie 设
置为 10 天后过期,可以这样实现:
<script language="JavaScript" type="text/JavaScript">
<!--
// 获取当前时间
var date=new Date();
var expireDays=10;
// 将 date 设置为 10 天以后的时间
date.setTime(date.getTime()+expireDays*24*3600*1000);
// 将 userId 和 userName 两个 cookie 设置为 10 天后过期
document.cookie="userId=828; userName=hulk; expire="+date.toGMTString();
//-->
</script>
删除 cookie
为了删除一个 cookie ,可以将其过期时间设定为一个过去的时间,例如:
<script language="JavaScript" type="text/JavaScript">
<!--
// 获取当前时间
var date=new Date();
// 将 date 设置为过去的时间
date.setTime(date.getTime()-10000);
// 将 userId 这个 cookie 删除
document.cookie="userId=828; expire="+date.toGMTString() ;
//-->
</script>
指定可访问 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 操作及其函数实现。
添加一个 cookie : addcookie(name,value,expireHours)
该函数接收 3 个参数: cookie 名称, cookie 值,以及在多少小时后过期 。这里约定 expireHours 为 0 时 不设定过期时间,即当浏览器关闭时 cookie 自动消失 。该函数实现如下:
<script language="JavaScript" type="text/JavaScript">
<!--
function addcookie(name,value,expireHours){
var cookieString=name+"="+escape(value);
// 判断是否设置过期时间
if(expireHours>0){
var date=new Date();
date.setTime(date.getTime+expireHours*3600*1000);
cookieString=cookieString+"; expire="+date.toGMTString();
}
document.cookie=cookieString;
}
//-->
</script>
2 .获取指定名称的 cookie 值: getcookie(name)
该函数返回名称为 name 的 cookie 值,如果不存在则返回空,其实现如下:
<script language="JavaScript" type="text/JavaScript">
<!--
function getcookie(name){
var strcookie=document.cookie;
var arrcookie=strcookie.split("; ");
for(var i=0;i<arrcookie.length;i++){
var arr=arrcookie[i].split("=");
if(arr[0]==name)return arr[1];
}
return "";
}
//-->
</script>
3 .删除指定名称的 cookie : deletecookie(name)
该函数可以删除指定名称的 cookie ,其实现如下:
<script language="JavaScript" type="text/JavaScript">
<!--
function deletecookie(name){
var date=new Date();
date.setTime(date.getTime()-10000);
document.cookie=name+"=v; expire="+date.toGMTString();
}
//-->
</script>
也可以用另一种网上流传的 :
<script language="JavaScript" type="text/JavaScript">
// 写 cookies 函数 作者:翟振凯
function SetCookie(name,value)// 两个参数,一个是 cookie 的名子,一个是值
{
var Days = 30; // 此 cookie 将被保存 30 天
var exp = new Date(); //new Date("December 31, 9998");
exp.setTime(exp.getTime() + Days*24*60*60*1000);
document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString();
}
function getCookie(name)// 取 cookies 函数
{
var arr = document.cookie.match(new RegExp("(^| )"+name+"=([^;]*)(;|$)"));
if(arr != null) return unescape(arr[2]); return null;
}
function delCookie(name)// 删除 cookie
{
var exp = new Date();
exp.setTime(exp.getTime() - 1);
var cval=getCookie(name);
if(cval!=null) document.cookie= name + "="+cval+";expires="+exp.toGMTString();
}
SetCookie ("xiaoqi", "3")
alert(getCookie('xiaoqi'));
</script>
Cookies 怪兽
因为某些原因 Cookies 的名声很不好。许多人利用 cookies 做一些卑鄙的事情,比如流量分析、点击跟踪。 Cookies 也不是非常安全,特别是没有 secure 属性的 cookies 。不过,即使你用了安全的 cookies ,如果你和别人共用计算机,比如在网吧,那么别人就可以窥探计算机硬盘上未加密保存的 cookie 文件,也就有可能窃取你的敏感信息。所以,如果你是一个 WEB 开发人员,那么你要认真考虑这些问题。不要滥用 cookies 。不要把用户可能认为是敏感的数据保存在 cookies 里 。如果把用户的社会保险号、信用卡号等保存在 cookie 里,等于把这些敏感信息放在窗户纸下,无异于把用户投到极大危险之中。一个好的原则是,如果你不想陌生人了解你的这些信息,那就不要把它们保存在 cookies 里。
另外, cookies 还有一些实际的限制。 Cookies 保留在计算机上,不跟着用户走。如果用户想换计算机,那么新计算机无法得到原来的 cookie 。甚至用户在同一台计算机上使用不同浏览器,也得不到原来的 cookie : Netscape 不能读取 Internet Explorer 的 cookies 。
还有,用户也不愿意接受 cookies 。所以不要以为所有的浏览器都能接受你发出的 cookies 。如果浏览器不接受 cookies ,你要保证自己的 WEB 站点不致因此而崩溃或中断。
另外 WEB 浏览器能保留的 cookies 不一定能超过 300 个 。也没有标准规定浏览器什么时候、怎么样作废 cookies 。所以达到限制时,浏览器能够有效地随机删除 cookies 。 浏览器保留的来自一个 WEB 服务器上的 cookies ,不超过 20 个,每个 cookie 的数据(包括名称和值),不超过 4K 字节。 ( 不过,本文里的 cookie 尺寸没问题,它只占了 12 K 字节,保存在 3 个 3 cookies 里。 )
简而言之,注意保持 cookie 简单 。不要依赖 cookies 的存在,不要在每个 cookie 里保存太多信息。不要保存太多的 cookes 。但是,抛除这些限制,在技巧高超的 WEB 管理员手里, cookie 的概念是一个有用的工具。