初学者容易将cookie和session搞混淆,也有不少人简单的把cookie和session简单的理解为一种为客户端存储机制,另一种为服务端存储机制。实际上cookie和session不只是这么简单的,这一章就来详细讲解下关于cookie和session的内容。
1 Cookie的基本概念和设置
Cookie是一种存储在客户端的数据,能存储cookie的客户端不只是浏览器,但绝大多数情况下都是由浏览器来实现。浏览器通过http协议和服务端进行cookie交互。Cookie是独立于语言而存在的,很多种语言都可以设置和读取cookie。在实现过程中,编程语言是通过指令通知浏览器,然后是浏览器实现设置cookie的功能的。而读取cookie则是通过浏览器请求服务端时携带的http头部中的cookie信息得来的。
PHP中可使用setcookie()来设置cookie,语法如下:
bool setcookie ( string $name [, string $value = "" [, int $expire = 0 [, string $path = "" [, string $domain = "" [, bool $secure = false [, bool $httponly = false ]]]]]] )
setcookie可定义cookie并将其随http头部一起发送给客户端,在设置cookie之前不能有任何输出。当cookie被设置后,可在刷新页面后通过$_COOKIE全局数组获得。
第一个参数name是必选参数,表示cookie的名称,cookie的值是通过$_COOKIE[name]获得的。
第二个参数是设置的cookie的值,存储在客户端。
第三个参数是设置cookie的有效时间,以秒为单位,如果想要删除一个函数可以将cookie的有效时间设置为当前时间之前,或者使用unset($_COOKIE[name])来删除某个cookie。如果不设置这个值,当浏览器关闭时,cookie会随之失效。
参数path设置cookie的有效目录,如果设置为”/“则表示在当前目录下均可用,如果设置为”/foo/“则表示只有在目录 “/foo/“ 和其子目录如”/foo/bar/“下才可。
参数domain设置cookie的作用域名,默认在本域名下有效。如果设置该值为”Example Domain则改该域名下的所有子域名如i.e.w2.Example Domain都可使用该cookie。如果要设置一个域名的所有子域名都可使用,则设置其值为如example.com即可。
参数secure用来设置是否对cookie进行加密传输,默认为false。如果设置为true,则只有在使用https的时候才会设置cookie。
第七个参数如果为true则表示只能通过http协议才能访问该cookie,意味着客户端javascript就不可操作这个cookie。使用此参数可减少XSS攻击的风险。
下面使用PHP分别设置三个cookie:
<?php
setcookie('name','chenxiaolong');
setcookie('num','100',time()+100,'/foo/');
setcookie(‘gender’,'male',time()+100,'','百度一下,你就知道');
print_r($_COOKIE);
?>
第一个cookie设置名为name,值为chenxiaolong ,其他参数都是默认值,表示在当前目录和域名下都有效,且有效时间持续到浏览器关闭。第二和第三个cookie的设置只在特定的目录域名和有效时间内才能看到。注意当第一次在浏览器访问这个脚本文件时,并不会有任何的输出,因为设置完cookie后,需要刷新页面在下次请求时http头部才会携带上一次设置的cookie信息,这时才能读取到cookie。
第一次在浏览器访问该脚本的请求消息头(Request Headers)和响应消息头(Response Headers)分别如下:
Request Headers:
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:zh-CN,zh;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Host:localhost
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36
可见其并没有携带任何的cookie信息,说明浏览器并没有向客户端发送任何的cookie信息,而返回的响应消息头中包含了cookie信息。
Response Headers:
Connection:Keep-Alive
Content-Length:10
Content-Type:text/html; charset=UTF-8
Date:Sun, 13 Nov 2016 08:48:14 GMT
Keep-Alive:timeout=5, max=100
Server:Apache/2.4.16 (Unix) PHP/7.0.5
Set-Cookie:name=chenxiaolong
Set-Cookie:num=100; expires=Sun, 13-Nov-2016 08:49:54 GMT; Max-Age=100; path=/foo/
Set-Cookie:gender=male; expires=Thu, 01-Jan-1970 00:00:10 GMT; Max-Age=-1479026884; domain=百度一下,你就知道
X-Powered-By:PHP/7.0.5
返回消息头中包含三个 Set-Cookie 部分,这是通知浏览器设置对应的Cookie。当我们再次刷新页面的时候,可看到请求消息头中携带了Cookie信息。刷新请求的得到的请求消息头如下:
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:zh-CN,zh;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Cookie:name=chenxiaolong
Host:localhost
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36
Name
可见其中已经携带了Cookie信息,但是只有设置的name这一个Cookie,这是因为其他两个Cookie不在这个目录或本域名下有效。
我们在前面已经讲过,既然PHP和客户端javascript都可以操作cookie,那么用php设置的cookie也可用javascript读取到,用javascript设置的cookie也可由php读取到。不同的时,php设置的cookie需要在刷新页面后的下一次请求中才有效,而javascript设置的cookie在本次请求中既有效。
如下用javascript代码设置cookie:
<script type="text/javascript">
function setCookie(name,value)
{
var Days = 30;
var exp = new Date();
exp.setTime(exp.getTime() + Days*24*60*60*1000);
document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString();
}
function getCookie(name)
{
var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
if(arr=document.cookie.match(reg))
return unescape(arr[2]);
else
return null;
}
setCookie('test','testhaha');
alert(getCookie('test'));
</script>
浏览器访问本页用javascript设置的cookie会立即生效。我们再来看访问这个页面的请求消息头和响应消息头,分别如下。
Request Headers:
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:zh-CN,zh;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Cookie:test=testhaha
Host:localhost
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36
由于使用的是javascript在客户端设置的cookie,所以在本次向服务端发送http请求时就已经携带了cookie信息。我们再用php代码 echo $_COOKIE[‘test']; 来获得由javascript设置的cookie,此时可在页面成功打印出名为test的cookie的值。通过这个例子我们更清晰的知道,cookie是由编程语言通过一些指令告知浏览器设置的,由浏览器实现,在浏览器和服务端进行通信时,在http消息头中携带cookie信息。
2 cookie的应用和存储机制
Cookie经常用来存储一些不敏感的信息,可用来防止刷票,记录用户名,限制重复提交等。
以防止用户在一分钟之内多次提交为例,代码如下:
<script type="text/javascript">
function SetCookie(name, value) {
var Days = 30;
var exp = new Date();
exp.setTime(exp.getTime() + 60 * 100);//过期时间 1分钟
document.cookie = name + "=" + escape(value) + ";expires=" + exp.toGMTString();
}
function submit() {
if(getCookie('submit')) {
alert('you haved submited before,please submit after one minute');
} else {
SetCookie('submit','yes');
}
}
function getCookie(name)
{
var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
if(arr=document.cookie.match(reg))
return unescape(arr[2]);
else
return null;
}
</script>
<button onclick='submit()'>提交</button>
以上代码实现的是防止用户在一分钟之内多次提交表单,当用户第一次提交表单时,设置cookie有效期为1分钟,当再次点击提交时,判断cookie是否过期来限制用户的提交。
前面说,Cookie是存储在客户端的一段数据。但是不同的浏览器存储Cookie的地方不同,一种是将Cookie数据保存在文件中,另一种是保存在浏览器内存中。
在Windows系统上(这里以Win7为例)。IE浏览器Cookie数据位于%APPDATA%MicrosoftWindowsCookies 目录中的xxx.txt文件 ,里面可能有很多个.txt Cookie文件,如:C:Usersyren9AppDataRoamingMicrosoftWindowsCookies0WQ6YROK.txt
在IE浏览器中,IE将各个站点的Cookie分别保存为一个XXX.txt这样的纯文本文件;而Firefox和Chrome是将所有的Cookie都保存在一个文件中,该文件的格式为SQLite数据库格式的文件。Firefox的Cookie数据位于:%APPDATA%MozillaFirefoxProfiles 目录中的xxx.default目录,名为cookies.sqlite的文件。如:C:UsersjayAppDataRoamingMozillaFirefoxProfilesji4grfex.defaultcookies.sqlite
在Firefox中查看cookie, 可以选择”工具 > 选项 >” “隐私 > 显示cookie”。Chrome的Cookie数据位于:%LOCALAPPDATA%GoogleChromeUser DataDefault 目录中,名为Cookies的文件。如:C:UsersjayAppDataLocalGoogleChromeUser DataDefaultCookies 。
本文节选自 《php7实践指南》 陈小龙著
微信扫一扫,发现更多内容
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。