php7实践指南-ch14Cookie与Session-Cookie详解

初学者容易将Cookie和Session搞混淆,也有不少人简单地把Cookie和Session理解为一种是客户端存储机制、另一种是服务端存储机制。实际上Cookie和Session不只是这么简单的,这一章就来详细讲解下关于Cookie和Session的内容。

14.1 Cookie详解

14.1.1 Cookie的基本概念和设置

Cookie是一种存储在客户端的数据,能存储Cookie的客户端不只是浏览器,但绝大多数情况下都是由浏览器来实现的。浏览器通过HTTP协议和服务端进行Cookie交互。Cookie是独立于语言而存在的,很多种语言都可以设置和读取Cookie。在实现过程中,编程语言是通过指令通知浏览器,然后是浏览器实现设置Cookie的功能的。读取Cookie则是通过浏览器请求服务端时携带的HTTP头部中的Cookie信息得来的。

PHP中可使用setcookie()来设置cookie,语法如下:

setcookie ( string $name , string $value = "" , int $expires = 0 , string $path = "" , string $domain = "" , bool $secure = false , bool $httponly = false ) : bool

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的作用域名,默认在本域名下有效。如果设置该值为“http://www.example.com”则该域名下的所有子域名如i.e.w2.http://www.example.com都可使用该cookie。如果要设置一个域名的所有子域名都可使用,设置其值为example.com即可。

参数secure用来设置是否对Cookie进行加密传输,默认为false。如果设置为true,那么只有在使用https的时候才会设置Cookie。

第七个参数如果为true就表示只能通过HTTP协议才能访问该Cookie,意味着客户端JavaScript不可操作这个Cookie。使用此参数可减少XSS攻击的风险。

下面使用PHP分别设置三个Cookie:

<?php
setcookie('name',"chenxioalong");
setcookie('num','100',time()+100,'/foo/');
setcookie("gender",'male',time()+100,'','php.jingpan.io');
print_r($_COOKIE);

第一个Cookie设置名为name、值为chenxiaolong,其他参数都是默认值,表示在当前目录和域名下都有效,且有效时间持续到浏览器关闭。第二个和第三个Cookie的设置只在特定的目录域名和有效时间内才能看到。注意当第一次在浏览器访问这个脚本文件时并不会有任何输出,因为设置完Cookie后需要刷新页面,这样在下次请求时HTTP头部才会携带上一次设置的Cookie信息,这时才能读取到Cookie。

第一次在浏览器访问该脚本的请求消息头(Request Headers)和响应消息头(Response Headers)分别如下:

Request Headers

GET /php_practice_guide/ch14cookie_session/setcookie1.php HTTP/1.1
Host: php.jingpan.io
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36 Edg/87.0.664.75
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6

可见其并没有携带任何Cookie信息,说明浏览器并没有向客户端发送任何Cookie信息,而返回的响应消息头中包含了Cookie信息。

Response Headers

HTTP/1.1 200 OK
Date: Thu, 21 Jan 2021 04:35:51 GMT
Server: Apache
Set-Cookie: name=chenxioalong
Set-Cookie: num=100; expires=Thu, 21-Jan-2021 04:37:31 GMT; Max-Age=100; path=/foo/
Set-Cookie: gender=male; expires=Thu, 21-Jan-2021 04:37:31 GMT; Max-Age=100; domain=php.jingpan.io
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8

返回消息头中包含3个Set-Cookie部分,用于通知浏览器设置对应的Cookie。当我们再次刷新页面的时候,可看到请求消息头中携带了Cookie信息。刷新请求得到的请求消息头如下:

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cache-Control: max-age=0
Connection: keep-alive
Cookie: name=chenxioalong; gender=male
Host: php.jingpan.io
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36 Edg/87.0.664.75

可见其中已经携带了Cookie信息。

我们在前面已经讲过,既然PHP和客户端JavaScript都可以操作Cookie,那么用PHP设置的Cookie也可用JavaScript读取到,用JavaScript设置的Cookie也可由PHP读取到。不同的是,PHP设置的Cookie需要在刷新页面后的下一次请求中才有效,而JavaScript设置的Cookie在本次请求中就有效。

下面用JavaScript代码设置Cookie:

cookie.html

<html>
<head>
    <script type="text/javascript">
        function setCookie(name,value) {
                var Days = 30;
                var exp = new Date();
                exp.setTime(exp.getTime() + Days*24*60*60*1000);
                //alert(exp);
                //alert(exp.toGMTString());
                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'));
        //alert(document.cookie.toString());
    </script>
</head>
<body>

</body>
<form enctype="multipart/form-data" action="cookie.php" method="POST">
    Send this file:<input name="userfile" type="file"/>
    <input type="submit" value="Send file"/>
</form>
</html>

cookie.php

<?php
echo $_COOKIE['test'];

浏览器访问本页用JavaScript设置的Cookie会立即生效。我们再来看访问这个页面的请求消息头和响应消息头: 

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cache-Control: max-age=0
Connection: keep-alive
Content-Length: 192
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary1BaxU99HrnAiRADj
Cookie: test=testhaha
Host: php.jingpan.io
Origin: http://php.jingpan.io
Referer: http://php.jingpan.io/php_practice_guide/ch14cookie_session/cookie.html
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36 Edg/87.0.664.75

由于使用的是JavaScript在客户端设置的Cookie,所以在本次向服务端发送HTTP请求时就已经携带了Cookie信息。我们再用PHP代码echo $_COOKIE['test'];来获得由JavaScript设置的Cookie,此时可在页面成功打印出名为test的Cookie值。通过这个例子更清晰地知道,Cookie是编程语言通过一些指令告知浏览器,由浏览器实现的,浏览器和服务端进行通信时,HTTP消息头中携带了Cookie信息。

14.1.2 Cookie的应用和存储机制

Cookie经常用来存储一些不敏感的信息,如用来防止刷票、记录用户名、限制重复提交等。这里以防止用户在一分钟之内多次提交为例,代码如下:

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <script type="text/javascript">
        function setCookie(name,value) {
            var Days = 30;
            var exp = new Date();
            exp.setTime(exp.getTime() + 60*1000); //过期时间为1分钟
            //alert(exp);
            //alert(exp.toGMTString());
            document.cookie = name + "="+ escape(value) + ";expires=" + exp.toGMTString();

        }

        function submit(){
            if(getCookie('submit')){
                alert('you haved submited befor,please submit after one minute');
            }else{
                setCookie('submit','yes');
                alert('submit sucess.');
            }
        }

        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>
</head>
<body>

</body>
<button onclick="submit()">提交</button>
</html>

以上代码实现的是防止用户在一分钟之内多次提交表单,当用户第一次提交表单时,设置Cookie有效期为1分钟,当再次提交时判断Cookie是否过期来限制用户的提交。

前面说,Cookie是存储在客户端的一段数据,但是不同的浏览器存储Cookie的地方不同:一种是将Cookie数据保存在文件中,另一种是保存在浏览器内存中。

在Windows系统上(这里以Windows 7为例)。IE浏览器Cookie数据位于%APPDATA%\Microsoft\Windows\Cookies\ 目录中的xxx.txt文件,里面可能有很多个.txt Cookie文件,如C:\Users\yren9\AppData\Roaming\Microsoft\Windows\Cookies\0WQ6YROK.

在IE浏览器中,IE将各个站点的Cookie分别保存为一个XXX.txt这样的纯文本文件;而Firefox和Chrome是将所有的Cookie都保存在一个文件中,该文件的格式为SQLite数据库格式的文件。Firefox的Cookie数据位于%APPDATA%\Mozilla\Firefox\Profiles\ 目录中的xxx.default目录下,名为Cookies.sqlite的文件中,如C:\Users\jay\AppData\Roaming\Mozilla\Firefox\Profiles\ji4grfex.default\cookies.sqlite。

在Firefox中查看Cookie,可以选择“工具>选项>隐私>显示Cookie”。Chrome的Cookie数据位于%LOCALAPPDATA%\Google\Chrome\User Data\Default\目录中名为Cookies的文件中,如C:\Users\jay\AppData\Local\Google\Chrome\User Data\Default\Cookies。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值