PHP 第4章 cookie和session PHP 第4章 cookie和session

2019-08-24

一、会话控制

①、出现原因

http 是无状态协议的,每次都是不同的服务器请求,无法维护两个请求事务之间的关系。

②、会话控制

能够在网站中跟踪一个变量,通过对变量的跟踪,就可以使多个请求事物之间建立联系,根据授权和用户身份显示不同的内容、不同页面。

③、会话跟踪技术

(1)使用隐藏域表单,提交给php脚本

https://file.lulublog.cn/images/3/2022/08/R18zeY0L1GDk48yd0i03113r3Gi0i4.png

(2)url 重写:将唯一会话的id添加到url结尾来进行标识,使用超链接或者header()函数

http://www.luluyii.cn/post/default/show-post?id=9

(3)cookie:将唯一的会话 id 存放在客户端

(4)session:将唯一的会话id存放在服务器端

二、cookie

①、基本介绍

(1)cookie 是在 http 协议下,服务器或脚本在客户端保存维护信息的一种方式。

(2)cookie 是 web 服务器保存在客户端的一个很小的文本文件,保存客户端的信息,提高网页的处理效率,降低服务器负担

(3)cookie保存在客户端,通常在浏览器的 cookie 临时文件夹中,可以手动的删除,如果 cookie 太多超过系统的允许范围,系统将自动删除。

②、cookie 的操作

(1)创建 cookie:setcookie("key","value",time()+秒)

A setcookie 为头信息设置,在此之前不能有任何输出

B setcookie(name,value,expire,path,domain,secure)

Name:调用名为 cookiename 的 cookie;
value: name 对应的值 
exprice:设置 cookie 的过期时间和日期,用一个标准的 Unix 时间标记,可以用 time()函数取得,以秒为单位 
path:服务器端的有效路径,设置为“/”表示这个域中所有数组都可以被访问读取 
Domain:设定 cookie 有效域名 
secure:指明 cookie 只能通过安全的 https 传送, 设为 true 时只能通过安全的 https,默认为 false, 即设置是否仅在 https 安全连接时才发送 cookie 到客户端:0或 1

(2)获取 cookie 信息:$_COOKIE['key']

(3)删除 cookie

//方式1:设置值为空 setcookie("username",""); 
//方式2:设置过期时间 setcookie("username","lulubin",time()-1);

③、cookie 的实际应用:设置并获取上次访问时间

setcookie("lastVisit",date("Y-m-d H:i:s"),time()+24*3600*30); 
echo "上次访问时间是:".$_COOKIE["lastVisit"];

三、session

①、基本介绍

session 从用户访问页面开始,到断开与网站的连接为止,形成一个会话的生命周期。在会话期间,分配客户唯一的一个 sessionID(下面的l7e7rl2809tscmgcgi86qegra0),用来标识当前用户,与其他用户进行区分。

②、session 的操作

(1)、初始化 session:session_start( )

session 默认是关闭的,可通过 php,ini 配置文件 session.auto_start = 0

(2)、保存 session 数据:$_SESSION['name'] = 'lulubin'

(3)、session 会话时,session 会分别保存在客户端和服务器端得两个文件

A 对于客户端:使用临时的 cookie 保存(cookie的名称为PHPSESSID)或者通过 url 字符串的形式传递;

获取 cookie 的名称 
echo session_name(); //输出 PHPSESSID
获取 cookie 的值 
echo $_COOKIE["PHPSESSID"]; //输出l7e7rl2809tscmgcgi86qegra0 
session_start(); //注意必须开始 session ,才可以获取用 session_id() 获取到 cookie 的值 
echo session_id(); //输出l7e7rl2809tscmgcgi86qegra0

注意:可通过 session_name('你想要设计的名称')来 sessionName,即设置 cookie的 名称,但必须在 session_strat() 之前

session_name("mySession");
session_start();
$_SESSION["name"]="lulubin";

注意:可通过 session_id('你想要设计的名称') 来设置 sessionID,即设置 cookie的 value,但必须在session_start()之前。

session_id("luluyii");
session_start();
$_SESSION["name"]="lulubin";

此时你会发现 cookie 的值为 luluyii

B 对于服务器端也以文本的形式保存在指定的 session 目录中。

打开上述目录,发现新增了一个文件,文件名为 sess_l7e7rl2809tscmgcgi86qegra0

注意:如果上面重新设置了 sessionID ,则文件名你设置的 session_id,如上面的 luluyii

(4)打开 sess_l7e7rl2809tscmgcgi86qegra0 文件

注意:session文件的默认存放时间是 1440 秒,即 sess_l7e7rl2809tscmgcgi86qegra0 文件存放 1440 秒后被删除

//获取 session 的值
session_start();
echo $_SESSION["name"]; //输出 lulubin

小技巧:sessionID(比如上面的l7e7rl2809tscmgcgi86qegra0) 可以作为会话信息保存到数据库中,进行 session 持久化。

这样可以跟踪用户的登陆次数,在线与否,在线时间。

(5)删除 session

A unset( ):用于删除单个session变量

首先,我们先新增两个 session:S_SESSION['password'] = '123456';

然后,打开 sess_l7e7rl2809tscmgcgi86qegra0 文件,你会发现该文件多了两个数据

然后删除 password 数据:unset($_SESSION['password']),打开文件

B session_unset():删除所有的 session 变量

使用 session_unset() 或者 $_SESSION=array(),打开文件,所有数据都被删除了

C session_destroy(),执行这个函数,你会发现 sess_l7e7rl2809tscmgcgi86qegra0 文件被删除了

③、cookie 和 session 的区别

(1)相同点:都可以在解决 http 无状态的问题,使同一个客户端在访问网站的多次请求中,可以保存、设置信息,并且在整个web应用中共享。

(2)不同点:cookie 的信息保存在客户端,session 的信息保存在服务器端。

(3)联系:当使用基于 cookie 的 session 时,sessionID 一般保存在 cookie 中。

④、如果cookie禁用了,session还能用吗,为什么

session 的运行依赖 session id,而 session id 是存在 cookie 中的,也就是说,如果浏览器禁用了 cookie ,同时 session 也会失效(但是可以通过其它方式实现,比如在 url 中传递 session_id)

⑤、php.ini 中配置 session

session.auto_start=0;//在请求启动时初始化,无需每次手动sessin_start(),
不过该选项有一些限制,不能将对象放入会话,因为类的定义必须在会话之前加载在会话中重建对象
session.cache_expire=180; //设置缓存中的会话过期时间在n分钟后
session.cookie_lifetime=0; //设置按秒记的cookie的保存时间,0表示知道浏览器被重启
session.cookie_path=/; //cookie的有效路径
session.cookie_domain=; //cookie的有效域
session.name=PHPSSESID; //又在cookie里的session_name()
session.save_hander=files; //用于保存/取回数据的控制方式
session.save_path=/tmp; //在save_handler设为文件是传给控制器的参数,这是数据文件的保存路径
session.user_cookie=1; //是否使用cookies
session.gc_maxlifetime=40; //指定过了多少秒之后数据就会被视为“垃圾”,并被清楚
session.gc_probability=1//
session.gc_divisor=100;//这两个合起来就是启动gc进程管理概率的,在session初使化时(session_start())
session.gc_probability/session.gc_divisor:1/100,在session_start100次,有一次的概率删除垃圾文件

⑥、Session的默认保存路径

在php.ini里的配置session.save_path是注释掉的,那么Seesion保存的路径在不同类型操作系统保存在什么位置?

Linux: /tmp 或 /var/lib/php/session

Windows: C:\WINDOWS\Temp 也可以去搜索以"sess_"开头的文件,来查找Seesion保存的路径

⑦、如何修改SESSION的生存时间

  • 方法1:将php.ini 中的 session.gc_maxlifetime 设置为 9999 重启 apache/nginx

  • 方法2:

session_start(); 
$lifeTime = 24 * 3600; 
setcookie(session_name(), session_id(), time() + $lifeTime, "/");
  • 方法3:

$lifeTime = 24 * 3600; 
session_set_cookie_params($lifeTime); 
session_start();

⑧、类的属性可以序列化后保存到session 中,从而以后可以恢复整个类,这要用到的函数是

string serialize ( mixed $value )
  • serialize() 返回字符串,此字符串包含了表示 value 的字节流,可以存储于任何地方。

    这有利于存储或传递 PHP 的值,同时不丢失其类型和结构。

  • 想要将已序列化的字符串变回 PHP 的值,可使用 unserialize()。

  • serialize() 可处理除了 resource之外的任何类型。甚至可以 serialize() 那些包含了指向其自身引用的数组。

  • 当序列化对象时,PHP 将试图在序列动作之前调用该对象的成员函数 __sleep()。这样就允许对象在被序列化之前做任何清除操作。类似的,当使用 unserialize() 恢复对象时, 将调用 __wakeup() 成员函数。

⑨、写出 session 的运行机制

  • 用户 A 访问站点 Y,如果站点 Y 执行了session_start();(以下假定session_start()总是存在)

  • 那么会产生一个 session_id,这个 session id 一般会以 COOKIE 的形式保存到用户A(我们可以通过在 php.ini 里设置 session.use_only_cookies 为 1,强制 SESSION ID 必须以COOKIE 传递)。

  • 这时候 SESSION ID 表现为 $_COOKIE['PHPSESSID'];(PHPSESSID 可用 session_name() 函数来修改)

  • 用户 A 接着访问,这个 session id($_COOKIE['PHPSESSID'])就会在 A 每次访问 Y 的时候传送到站点 Y。

  • 在站点 Y 上,会有这么一个目录,是用来保存 SESSION 的实际数据的。

  • 站点 Y 接收到 session id,然后通过 session id,来获得与 SESSION 数据的关联,并返回 SESSION 数据。

⑩、session_set_save_handler

代码下载

运行结果:

open
read
我是最后脚本结束register_shutdown_function调用
write
close

默认是 session_start 分别调用的回调函数为 open read ,然后等待脚本结束,收集$_SESSION(默认在内存中),然后关闭脚本,然后执行write,写入文件,然后close

改变默认session回调顺序

那么我们使用 session_commit(); 或者 session_write_close();函数调用的时候,session的机制就改变了,直接写入文件,关闭文件。然后再执行脚本。

运行结果:

open
read
write
close
我是最后脚本结束register_shutdown_function调用

那么 session_dessory 调用的时候,就是在 read 之后,因为只要 sesson_start 开启,先执行的就是 open 和read。 

那么 gc 呢,我们都知道 gc 是根据 session.gc_probability 和 session.gc_divisor 参数控制。

本例中我设置了他们的比例为 5,如果命中 gc,而且没有调用 session_commit(); 或者 session_write_close(); 函数

运行结果:

open
read
gc
我是最后脚本结束register_shutdown_function调用
write
close
阅读 2186