07 会话cookie和session
概述
简介
Web会话:用户打开一个浏览器,访问某一个web站点,在这个站点点击访问多个超链接,访问服务器的多个资源,然后关闭浏览器,整个过程就是一个会话
由于HTTP 协议的特点是无状态/无连接,当一个浏览器连续多次请求同一个 web 服务器时,服务器是无法区分这多个操作是否来自于同一个浏览器(用户)。而会话技术就是通过 HTTP 协议想办法让服务器能够识别来自同一个浏览器的多次请求,从而方便流览器(用户)在访问同个网站的多次操作中,能够持续进行,而不需要进行额外的身份验证
会话的本质还是为了实现跨脚本共享数据
分类
cookie技术:将数据存储到浏览器(客户端)
Cookie是在http协议下,服务器或脚本可以维护客户工作站上信息的一种方式。
Cookie 是 Web 服务器保存在用户浏览器(客户端)上的小文本文件,它可以包含有关用户的信息
无论何时用户链接到(通过HTTP请求头携带数据)服务器,Web站点都可以访问 Cookie信息
session技术:将数据存储到服务端
Sessio 在计算机专业术语中,session是指一个终端用户与交互系统进行通信的时间间隔,通常指从注册进入系统到注销退出系统之间所经过的时间。以及如果需要的话,可能还有一定的操作空间。
session 技术是将数据保存到服务器端,无论何时用户链接到服务器,web站点都可以访问 Session信息
区别
1. 安全性方面
- session存储数据在服务端,安全性高
- cookie存储数据在浏览器端,安全性低
2. 数据大小方面
- cookie数据存储的数量和带下都有限制(20个/4K)
- session数据存储不限
3. 可用数据类型
- cookie只能存储简单类型,数值、字符串
- session可以存储复杂类型,自动实现序列化
Cookie
原理
服务器将数据通过HTTP响应存储到浏览器上,浏览器再携带对应的Cookie数据访问服务器
Cookie技术可以实现跨脚本共享数据
- 第一次请求时,php通过setcookie函数将数据通过http协议响应头传输给浏览器
- 浏览器再第一次响应时,将cookie数据保存到浏览器
- 浏览器后续再请求同一个网站的时候,会自动检测是否存在cookie数据,如果存在,将会在请求头中携带对应的数据到服务器
- php在执行的时候,会自判断浏览器请求中是否携带cookie,如果携带了cookie,会自动保存到$_cookie中
- 最后利用$_cookie访问cookie数据
设置Cookie
<?php
// 默认不设定时间戳,生命周期在关闭浏览器的时候,就会话结束了
setcookie('name1', 'song');
setcookie('name2', 'song');
// 设置7天的时间有效期:从现在开始 7天卮过期
setcookie('name3', 'song', time() + 7 * 24 * 60 * 60);
setcookie('name3', 'song', 0); // 默认0 是浏览器关闭
// 设定作用范围
setcookie('name4', 'song', time() + 7 * 24 * 60 * 60, '/');
// 不推荐:设定 伪数组 数据,默认是不支持的--一般不使用
setcookie('good_ids[0]', 1);
setcookie('good_ids[1]', 2);
setcookie('good_ids[2]', 3);
setcookie('good_ids[3]', 4);
读取Cookie
$_COOKIE['name'];
$_COOKIE['age'];
// 访问数组
$_COOKIE['good_ids'][1]
删除Cookie
实际上服务器是没有权限去操作浏览器上的内容的,所以也是不可能删除cookie的。
但是我们可以通过设定cookie的生命周期,让浏览器自动判定cookie失效,从而达到删除cookie的效果
// 方式一:清空内容
setcookie('name1','');
// 方式二:设定时间戳过期 time()就是当前时间
setcookie('name','song',time())
生命周期
cookie生命周期是指cookie在浏览器的存在时间(浏览器在下次访问时是否携带cookie,携带cookie说明cookie还存在
- 默认不设定周期:默认是关闭浏览器,cookie会话结束
- 设定一个日期时间戳,在该指定时间戳后,cookie会话失效
作用范围
作用范围:不同的层级文件中,设定的cookie默认是在不同的文件夹下有访问限制的:上层文件夹中设定的cookie可以在下层中访问,而子文件夹中设定的cookie是不可以在上层文件夹中访问的
- 默认:不设定,访问的范围就是默认的作用范围
- 设定为 '/' : 告知浏览器,cookie的作用范围是网站根目录
// 设定作用范围
setcookie('name4', 'song', time() + 7 * 24 * 60 * 60, '/');
cookie跨子域
跨子域:在同一级别域名下(baicu.com),可以有多个子域名(www.baidu.com和gz.baidu.com),各个子域名之间默认是不允许共享访问cookie数据的
跨域的设定:
// 设定 跨域地址
setcookie('name5', 'song', time() + 7 * 24 * 60 * 60, '/', 'www.baidu.com');
Session
原理
session与浏览器无关,但是与cookie有关
- php碰到session_start()时,开始session会话,会自动检测cookieID:如果cookie存在,使用现成的;如果cookie不存在,创建一个sessionID,并通过响应头以cookie形式保存到浏览器中
- 初始化超全局变量$_SESSIO为一个空数组
- php通过sessionID去指定session文件存储位置,匹配对应的文件:如果不存在该文件,创建一个sessionID命名的文件;存在该文件,读取文件内容(反序列化)将数据存储到$_SESSION中
- 脚本执行结束,将$_SESSION中保存的所有的数据序列化存储到sessionID对应的文件中
设置session
<?php
// 开启 session:任何时候,只要使用session,就需要开启(同一个脚本开启一次即可)
// 使用$_SESSION之前,必须要开启session
session_start();
// 设置
$_SESSION['name'] = 'song';
$_SESSION['age'] = 18;
$_SESSION['sex'] = '男';
$_SESSION['hobby'] = array('看书', '写字');
var_dump($_SESSION);
读取session
读取的方式和数组一样
<?php
// 开启 session:任何时候,只要使用session,就需要开启(同一个脚本开启一次即可)
// 使用$_SESSION之前,必须要开启session
session_start();
// 读取
var_dump($_SESSION);
echo $_SESSION['name'];
删除session
// 删除某个session,指定session下标即可
unset($_SESSION['name']);
// 删除所有session
$_SESSION=array();
session基础配置
可以在php.ini文件中查找到:
-
session.name:session名字,保存到 C00KIE 中,sessionID 对应的名字
-
session.auto_start:是否自动开启 session(无需手动 sessign_start()),默认是关闭的
-
sessign.save_handler:session 数据的保存方式,默认是文件形式
-
session.save_path:session 文件默认存储的位置
-
session.cookie_lifetime:PHPsessionID 在浏览器端对应 C00KIE 的生命周期,默认是会话结束
-
session.cookie.path:sessionID在浏览器存储之后允许服务器访问的路径(CO0KIE有作用范围)
-
session.sookie_domain:C00KIE 允许访问的子域,默认是智只能当前访问
如果需要配置,一般是使用脚本配置:
PHP可以通过 ini.set函数来在运行中设定某些配置项(只会对当前运行的脚本有效),把这种配置称之为项目级
ini_set('session.save.path','E://sessions');
销毁session
session删除是指删除 session 数据,在$_SESSION 中看不到而已
销毁 session 是指删除 session对应的 session 文件。
系统提供一个函数:session_destroy(),会自动根据 session_start()得到的 sessionID 去找到指定的 session 文件,并把其删除。
session_destroy();
session垃圾回收
垃圾回收机制的原理:
session 会话后,产生的session 文件并不会自动清除,如果每天有大量 session 文件产生但是又都是失效的,会增加服务器的压力和影响 session 效率。
垃圾回收,是指 session 机制提供了一种解决垃圾 session 文件的方式:给 session 文件指定周期,通过 session 文件最后更改时间与生命周期进行结合判定,如果已经过期则删除对应的 session 文件,如果没有过期则保留。这样就可以及时清理无效的僵尸文件,从而提升空间利用率和 session 工作效率
- 任何一次 session 开启(session_start()),session 都会尝试去读取 session 文件
- 读取 session 文件后,有可能触发垃圾回收机制(系统函数,自己触发,但是存在触发的几率)
- 垃圾回收机制会自动读取所有 session 文件的最后编辑时间,然后加上生命周期(配置文件)与当前时间进行比较:过期就删除;有效就保留
垃圾回收参数设置
- session.gc_maxlifetime=1440:规定的 session 文件最大的生命周期是 1440 秒,即24分钟
- session.gc_probability=1:垃圾回收概率因子(分子)
- session.gc_divisor=1000:垃圾回收概率分母,数字越大,触发的几率越小
其他
1. 禁用cookie功能后不能使用session的原因
session会话技术需要利用cookie技术来保存sessionID,从而使得php能够在夸脚本的时候得到相同的sessionID,从而访问同一个session文件,所以,禁用了cookie以后,session也不能使用了
2. 实现禁用COOKIE时也可以使用 SESSION
方案 1:可以利用 PHP 提供的session函数:session_id和session_name来获得和设置 sessionlD或者 name, 从而解决 session_start自动产生的新的sessionID的情况(手动操作)
// 脚本1
// 开启 session
session_start();
$id = session_id(); // 对应的值
$name = session_name(); // 就是php.ini中设置的session.name的值
echo $name . '' . $id;
// 传递给另一个脚本,即可实现跨脚本共享数据了
echo '<a href="XXX.php?{$name}={$id}">click</a>';
// 脚本2
// 接收传递过来的参数
$name = session_name();
$id = $_GET[$name];
// 设定sessionID,如果不设定,session_start就会自动生成新的sessionID
session_id($id);
// 开启 session
session_start();
// 读取
var_dump($_SESSION);
方案 2:可以利用 session 机制中已经提供的解决方案自动操作(配置):默认的session配置是只允许cookie保存sessionID
在php.ini文件中:
// 默认只允许cookie方式保存session,值为1
session.use_only_cookies=1
// 是否开启洽谈方式保存sid,默认0
session.use_trans_sid=0