面试-PHP篇-cookie和session

一、Cookie

(1)工作原理

        Cookie 是一种在远程浏览器端储存数据并以此来跟踪和识别用户的机制,是一种由服务器向客户端发送的片段信息。

        Cookie的中文含义是“小甜饼”,是很小很小的文件,它存储在客户端浏览器的内存或者硬盘上。包含在HTTP请求报文中,并在服务器中与浏览器之间传递。但是这个也不是服务器随意给浏览器的,需要浏览器使用Cookie为服务器记录一些信息。

         举个例子:把这个web服务器比作一家商场,商场里面的每个店面是一个web页面,而Cookie就相当于你第一次进入这家商场的时候商场给你办理的会员卡,但是会存储你的姓名手机号类似的 ,就会允许你在每一个店里享受优惠条件,只要在会员卡有效时间内,你任何时间都可以来这家商场拿着你的会员卡,你就会被看作商场的会员。

        看一下Cookie具体的流程:

用户第一次登陆输入登陆的信息(例如账号密码)然后请求服务器进行登陆,第一次登陆验证成功后。服务器通过在 HTTP 响应报文中设置一个 Set-Cookie 字段,并把 Cookie 数据放在 Set-Cookie 字段中以HTTP 报文传给浏览器;

浏览器在接收到 HTTP 响应报文后,检查到 Set-Cookie 字段有值,会在本地创建一个 Cookie 文件以键值对的形式来保存数据;

当浏览器再次向同一个服务器发送请求其他脚本时,浏览器会先搜索本地保存的 Cookie 文件,如果在 Cookie 文件中有任何与正在连接的 URL 相关的 Cookie,就在 HTTP 请求报文中设置一个 Cookie 字段,并把 Cookie 文件中的数据添加到该字段中,最后把携带 Cookie 字段的 HTTP 请求报文发送给服务器。

服务器的每个脚本都可以接受Cookie的数据,并重新对登陆者的身份进行验证,而不是每次用户都需要重新去输入登陆信息。

(2)PHP如何设置Cookie


       PHP 透明地支持 HTTP Cookie。Cookie是一种在远程浏览器端储存数据并以此来跟踪和识别用户的机制。可以用 setcookie() 或 setrawCookie() 函数来设置 Cookie。Cookie是 HTTP 标头的一部分,因此 setCookie() 函数必须在其它信息被输出到浏览器前调用,这和对 header() 函数的限制类似。可以使用输出缓冲函数来延迟脚本的输出,直到按需要设置好了所有的 cookie 或者其它HTTP头。

setcookie()函数

PHP官网setcookie()函数解释:
	https://www.php.net/manual/zh/function.setcookie.php
函数用法:
    setcookie ( string $name [, string $value = "" [, int $expire = 0 [, string $path = "" [, string $domain = "" [, bool $secure = false [, bool $httponly = false ]]]]]] ) : bool
作用:
	一旦设置 Cookie 后,下次打开页面时可以使用 $_COOKIE 读取。
参数:
	$name	Cookie的识别名称				  随后可以利用$_COOKIE['name']获取对应value
	$value	Cookie的值,以数值或者字符串形态	这个值储存于用户的电脑里,请勿储存敏感信息。
	$expire Cookie过期时间,以时间戳的形式 如果设置成零或者不写 Cookie 会在会话结束时过期(也就是关掉浏览器时)
	$path	Cookie有效的服务器路径, 默认值是设置 Cookie 时的当前目录。
	$domain	Cookie所属服务器的域名
	$secure	指明Cookie是否在安全的https下传递
	$httponly Cookie 仅可通过 HTTP 协议访问
返回值:
	如果在调用本函数以前就产生了输出,setcookie() 会调用失败并返回 FALSE。 如果 setcookie() 成功运行,返回 TRUE。


(3)设置Cookie并获取Cookie

$name = 'Tacks';
#isset检测变量是否已设置并且非 NULL 
if(!isset($_COOKIE['name'])){//第一次访问,浏览器还不知道cookie有name 
    setcookie('name',$name);//设置cookie name='Tacks'
}else{//第二次访问页面,浏览器知道cookie有name
    echo $_COOKIE['name'];//通过$_COOKIE全局数组进行获取对应的cookie值
}

 (4)设置过期时间

setcookie('name',$name,time()+60*60*24);//设置cookie name='Tacks'  过期时间一天

(5)设置保存路径

setcookie('name',$name,time()+60*60*24,'/php/');#设置其他目录进行保存

(6)可以看一下请求头的一些信息

       客户端浏览器第一次请求后,服务器设置对应Cookie返回携带到http请求头中,再次返回给客户端,客户端将其存储在本地,下一次客户端请求页面的时候,就会携带Cookie的请求头 。

(7)数组形态的Cookie

        通过带 数组[]标记的 Cookie 名称,也可以把 Cookie 设置成数组。 如果有数组元素,可以把它放进 Cookie 里; 脚本接收到时,Cookie 名称里的值会是一个数组。

$admin['name']  = 'Tacks';
$admin['pass']  = '12a@#$yh%^&*009238,.y+00-8~86GADB"28\3/ad42';#这里特殊符号比较多
$admin['power'] = 0;
#Cookie也可以利用多维数组的形式进行设置
setcookie('admin[name]',$admin['name']);
setcookie('admin[pass]',$admin['pass']);
setcookie('admin[power]',$admin['power']);

(8)获取Cookie二维数组的值

#上面存储admin二维数组获取
foreach($_COOKIE['admin'] as $key=>$value){
    echo $key,":",$value,'<br/>';
}
/*
name:Tacks
pass:12a@#$yh%^&*009238,.y+00-8~86GADB"28\3/ad42
power:0
*/

(9)setrawcookie()函数

setrawcookie() 和 setcookie() 非常相似,唯一不同之处是发送到浏览器的 cookie 值没有自动经过 URL(urlencode)编码。

(10)删除Cookie

           要删除一个 Cookie,应该设置过期时间为过去,以触发浏览器的删除机制。

setCookie('name','Tacks',time()-1);

二、Session
(1)工作原理
       Session技术与Cookie相似,都是用来存储用户的相关资料。但是最大的不同之处,在于Cookie是将数据存储在客户端中,而Session则是将数据存储在服务器系统下面。

      Session的中文含义是“会话”,在web系统中,通常指用户与web系统进行交互的过程,也就是从用户打开浏览器登陆到web系统中,到关闭浏览器退出web系统的这个过程。

 

      在Web发展历史上,Cookie技术的出现确实是一个重大的改革,但是Cookie在存储在客户端中可以进行修改。不太安全,另外用户如果篡改了,那么服务器也就不能正常追踪某个用户了。而Session技术是将用户相关的资料放在服务器下面,所以是相对安全的,用户无法停用Session的使用。

       举个例子:还是最上面那个商场的例子,用户去过商场后,Cookie好比用户自己存放一张会员卡在自己这里,但是如果会员卡丢失,那么就不能以会员方式进行购物了;而Session则是在用户办理卡的时候,由商场去记录用户的会员信息,这样下次用户去商场不需要带卡了,只需要报一下你的手机号(唯一标识符)或者会员卡号,商场就可以查到你的信息,进而判断你是否是会员。

      就这样客户端只需要存储由服务器为用户创建的一个Session标识符(相当于会员卡号),称之为SessionID,而在服务器端存储Session变量的值。SessionID是一个既不会重复又不容易找到规律的,由32位16进制数组成的字符串。SessionID是会保存在客户端的Cookie中。如果用户阻止Cookie的使用,可以将SessionID保存在用户浏览器地址URL中,当用户请求web服务器中,就会把SessionID发送给服务器,服务器再通过SessionID就可以提取保存在服务器中的Session变量,服务器可以利用全局变量$_SESSION进行共享变量。 

 

       Session 的工作机制是:为每个访客创建一个唯一的 id ( Session ID),并基于这个 Session ID 来存储变量。SessionID存储在 Cookie中,或者通过 URL 进行传导。有两种情况去传送SessionID, Cookie 方式相对好一些,但是用户可能在浏览器中关闭 Cookie;第二种方案就是把SessionID直接并入到 URL 中,以保证SessionID 的传送。无需开发人员干预,PHP 就可以自动处理 URL 传送SessionID 的场景。 如果启用了 session.use_trans_sid 选项, PHP 将会自动在相对 URL中包含会话 ID。

 

看一下Session具体的流程:

当浏览器第一次访问 PHP 脚本时,seesion_start() 函数会创建一个唯一的 Session ID(每个客户端都有一个唯一的标识),并自动通过 HTTP 的响应头,将这个 Session ID 保存到客户端 Cookie 中。同时,也在服务器端创建一个以 Session ID 命名的文件,用于保存这个用户的会话信息;

当同一个用户再次访问这个网站时,会自动通过 HTTP 的请求头将 Cookie 中保存的 Seesion ID 再携带过来;

服务器 PHP 脚本接受到客户端请求,这时 session_start() 函数就不会再去分配一个新的 Session ID,而是在服务器的硬盘中去寻找和这个 Session ID 同名的 Session 文件,将这之前为这个用户保存的会话信息读出。

 

(2)PHP设置Session与读取Session

Session的设置不同于Cookie,必须先进行启动。调用session_start()函数,以便让PHP的核心程序和Session相关的内建环境变量预先载入内存。session_start()函数作用启动新会话或者重用现有会话。

        基于Cookie的Session,在开启前不能有任何输出内容,因为此函数有设置头信息的内容。如果不想每次都进行session_start()开启,可以在php.ini里面设置“session.auto_start=1”。但是对象不能放入Session中,因为类定义要在session_start()开启前进行加载。

       另外可以通过$_SESSION超全局数组,进行赋值设置。执行下面代码后,默认情况下,PHP.ini 中设置的 SESSION 保存方式是 files(session.save_handler = files),即使用读写文件的方式保存 SESSION 数据,Session变量就会存储在服务器下的某个文件中,该文件的位置是通过php.ini中session.save_path属性指定的路径。
 执行后它会在服务端对应的存储目录下,生成一个以sess_后面跟着sessionID的文件。内容大致是"变量名|类型:长度:值;"的形式。另外在客户端可以看到下面会存储Cookie,其默认是PHPSESSID,值的内容就是存储的SessionID。

(3)销毁变量与销毁Session

如果您希望删除某些 session 数据,可以使用 unset() 或 session_destroy() 函数。例如用户向退出web系统,就需要提供一个注销功能。切记不要用unset($SESSION)注销整个Session数组,这样就不能通过($SESSION)超全局注册变量。

(4)Session的注销过程

PHP默认的Session是基于Cookie的,SessionID被服务器存储在客户端的Cookie中,所以在注销Session时也需要清除Cookie中保存的SessionID,而这就需要借助setCookie()函数完成。删除保存在客户端Cookie中的SessionID。从而销毁关于本次会话的所有相关资源。

      另外在PHP脚本中,可以通过调用session_name()函数获取Session名称, 如果指定name参数, session_name() 函数会更新会话名称, 并返回原来的会话名称。


(5)Session的垃圾自动回收机制

上面的四步走之后可以销毁本地会话,但是用户如果不直接点击退出,而是关闭浏览器。那么在服务器端的Session是不会被删除的,如果下次进行登陆,又会重新分配一个SessionID进行登陆,这个是因为在php.ini文件中默认设置session.cookie_lifetime=0,来进行设定SessionID在客户端Cookie 有效期,0指的是直到浏览器关闭。如果你设定的有效期(以秒为单位),那么不管你是否关闭浏览器,只要在有效期后,SessionID就会消失,从而客户端的SessionID也没有了,但是这个时候服务器的Session并没有删除,如果这样的垃圾文件越来越多,会影响服务器系统造成负荷,因此系统必须必须要有一种机制进行删除。

 

       设置Session后,服务器生成的Session文件就是一个小小的文本文件,是文件就会有一个修改时间的属性。那么垃圾回收机制就是根据这个时间来进行判断的。通过php.ini中设置session.gc_maxlifetime选项来设置一个时间(以秒为单位)。例如该选项的值是3600,那么系统垃圾回收程序,就会在所有的Session文件中进行排查,如果有文件的修改时间距离当前系统时间大于3600秒,就会将其删除,所以失去了客户端SessionID引用的文件,那么就访问不到该变量;同样如果没有失去客户端SeesionID的文件,只要用户在使用,那么Session文件修改时间就会更新,从而不会被删除。

 

      垃圾回收机制也是在开启session_start()时候启动的,但是有一个问题,一个网站的用户登陆多了,可能会多次调用session_start()开启会话,这样垃圾回收机制可能总是被调用,那么样就不是很合理,一天请求太频繁了。可以通过在php.ini里面设置session.gc_probaility和session.gc_divisor两个选项,进行设置启动回收程序的概率,计算公式大概是"session.gc_probaility/session.gc_divisor"。所以一般设置session.gc_probaility=1,选项session.gc_divisor=100,也就是调用session_start()函数开启会话100次才可能启动一次垃圾回收程序。会话请求越频繁,概率值应当越小。

(6)传递SessionID

通过上面的了解,我们知道客户端与服务器通过SessionID进行追踪一个用户,那么这个SessionID的传递方式有两种,默认是基于Cookie进行传递,另一种通过URL进行传递SessionID。

     如果客户端没有禁用Cookie,那么在PHP脚本中通过session_start()函数进行初始化,服务器会通过发送HTTP中会携带SessionID,客户端会响应到然后将其保存在浏览器Cookie中。

      如果禁用Cookie,那么浏览器中也就不会保存其SessionID,因而下次去请求服务器的时候,请求头中不会包含SessionID的信息,而服务器调用session_start()又会重新创建一个会话,这样就无法追踪用户状态。

     PHP中另一种传递会话ID机制,就是通过重写客户端请求的URL,把SessionID添加到URL中,这样服务端也可以接受到。无需开发人员干预,PHP 就可以自动处理 URL 传送会话 ID 的场景。 如果启用了 session.use_trans_sid 选项, PHP 将会自动在相对 URI 中包含会话 ID。详情可以看一下PHP官网对传递会话ID的方式。
 

三、Cookie与Session的区别

1.存放位置:

Cookie放在客户端浏览器中;

Session放在服务器端某个文件夹下;

2.存放的类型:

Cookie只能存放字符串。

Session还可以存放对象等其他类型。

3.存放大小:

Cookie存储的数据根据浏览器的不同而有不同的限制,Chrome大概是50左右,最大4097字节。

Session默认没有限制,但是如果过多的话,会影响服务器性能。

4.存放路径:

Cookie是可以用setcookie()函数设置路径参数的,如果同一个网站下不同路径的Cookie互相也是访问不到。

Session不能区分路径,同一个用户在会话期间,Session在任何一个地方都可以访问到。

5.生命周期:

Cookie是可以用setcookie()函数过期时间的,如果浏览器关闭,Cookie还没过期那么会存储到本地,下次打开浏览器的时候还有。如果没有设置过期时间一般是到浏览器关闭的时候就销毁了。

Session默认基于Cookie,然后默认设置session.cookie_lifetime=0也就是浏览器关闭的时候,会删除客户端Cookie,那么你就访问不到你之前的会话,而是新创建一个会话,但是远程服务器上的会话文件不会被删除(它会被垃圾回收机制进行处理);另外Session也可以用session.cookie_lifetime进行设定SessionID在客户端Cookie 有效期。

6.浏览器访问:

Cookie可以在不同浏览器下共享数据,都能访问到Cookie的信息。

Session只能在一个浏览器独享,常见的场景就是你如果登陆一个web系统后,复制链接到另一个浏览器上是需要重新进行登陆创建新的会话。

7.创建方式:

Cookie直接就可以用setcookie()进行设置。

Session必须先开启session_start(),然后用超全局变量$_SESSION['name'] = 'Tacks';进行设置。

8.手动销毁

Cookie利用 setCookie('name','Tacks',time()-1);设置过期就好了。

Session需要四步走,开启session_start(),然后删除对应的session变量$_SESSION = [];,然后让对应客户端的cookie也过期,然后彻底消除会话session_destroy();

9.用处

Cookie一般用于不重要的数据存储在浏览器上,如果想要更安全一些,可以利用一些加密算法处理后存放。

Session一般于登陆时候,存储会话状态。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章