风之旅人 Android Dev Engineer

15.PHP会话技术

2019-10-28
PHP

会话技术

会话技术介绍

web会话可简单理解为:用户开一个浏览器,访问某一个web站点,在这个站点点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。
HTTP协议的特点是无状态/无连接,当一个浏览器连续多次请求同一个web服务器时,服务器是无法区分多个操作是否来自于同一个浏览器(用户)。会话技术就是通过HTTP协议想办法让服务器能够识别来自同一个浏览器的多次请求,从而方便浏览器(用户)在访问同一个网站的多次操作中,能够持续进行而不需要进行额外的身份验证。

会话技术分类

  1. cookie技术 Cookie 是在 HTTP 协议下,服务器或脚本可以维护客户工作站上信息的一种方式。Cookie 是由 Web 服务器保存在用户浏览器(客户端)上的小文本文件(HTTP协议响应头) ,它可以包含有关用户的信息。无论何时用户链接到服务器(HTTP请求携带数据),Web 站点都可以访问 Cookie 信息
  2. session技术 Session直接翻译成中文比较困难,一般都译成时域。在计算机专业术语中,Session是指一个终端用户与交互系统进行通信的时间间隔,通常指从注册进入系统到注销退出系统之间所经过的时间。 以及如果需要的话,可能还有一定的操作空间。Session技术是将 数据保存到服务器端 ,无论何时用户链接到服务器,Web站点都可以访问Session信息:SESSION技术的实现是依赖COOKIE技术的。

两种会话技术区别(🌈身份证和银行卡的区别)

  1. 安全性方面 a. Session存储服务器端,安全性高 b. Cookie存储浏览器端,安全性低
  2. 数据大小方面 a. Cookie的数量和大小都有限制(20个/4K) b. Session数据存储不限
  3. 可用数据类型 a. Cookie只能存储简单数据,数值/字符串 b. Session可以存储复杂数据(自动序列化)
  4. 保存位置方面 a. Cookie保存在浏览器上 b. Session保存在服务器上

COOKIE

COOKIE原理

COOKIE技术:服务器将数据通过HTTP响应存储到浏览器上,浏览器可以在以后携带对应的COOKIE数据访问服务器。

  1. 第一次请求时,PHP通过setcookie函数将数据通过http协议响应头传输给浏览器
  2. 浏览器在第一次响应的时候将Cookie数据保存到浏览器
  3. 浏览器后续请求同一个网站的时候,会自动检测是否存在Cookie数据,如果存在将在请求头中将数据携带到服务器
  4. PHP执行的时候会自动判断浏览器请求中是否携带Cookie,如果写到,自动保存到 $_ COOKIE 中
  5. 利用 $_ COOKIE 访问 Cookie 数据

设置COOKIE信息

setcookie 函数用来设定 COOKIE 信息

setcookie (名字,值)

  1. cookie名的设置:字符串,第一个参数
  2. cookie值的设置:第二个参数
  3. cookie值的类型要求:必须是简单类型中的整数或者字符串
//设置COOKIE
setcookie('age',1);
setcookie('name','Martin');

🍎查看浏览器中的Cookie

读取COOKIE信息

🌈 COOKIE(会话技术)能够实现跨脚本共享数据

echo '<pre>';

//读取COOKIE
var_dump($_COOKIE);
🍎
array(3) {
  ["Phpstorm-6d42c3c3"]=>
  string(36) "544459c3-a698-4c59-8a6e-02f21677a31f"
  ["age"]=>
  string(1) "1"
  ["name"]=>
  string(6) "Martin"
}

COOKIE生命周期:COOKIE在浏览器生存时间(浏览器在下次访问服务器的时候是否携带对应的COOKIE)

  1. 默认(不设定)时的生命周期:不设定周期默认是关闭浏览器(会话结束)
  2. 设定为一个常规日期戳的周期:通过 setcookie 第三个参数可以限定生命周期,是用时间戳来管理,从格林威治时间开始
    //设置COOKIE
    setcookie('a1','a1');						           //普通COOKIE,浏览器关闭失效
    setcookie('a2','a2',7*24*60*60);			     //格林威治时间7天过期
    setcookie('a3','a3',time() + 7*24*60*60);	 //格林威治时间从现在开始7天后过期
    

    🍎

🐖 没有 “a2” 说明:浏览器发现本来就无效的COOKIE直接不保存

浏览器关闭后重新查看

发现只剩下 “a3”

  1. 设定为“0”的周期:在第三个参数设定生命周期的时候,用0代替时间戳:表示就是普通设置,会话结束过期 🌈 默认值为 0 , 即”到期时间”为”浏览会话结束时”
//0生命周期
setcookie('a4','a4',0);

🍎

  1. 删除一个cookie的做法:服务器没有权限去操作浏览器上的内容(不可能删除)。可以通过设定生命周期来让浏览器自动判定COOKIE是否有效:无效就清除
    • 4.1 清空COOKIE数据内容
    • 4.2 设定时间戳过期
//“删除”COOKIE

//setcookie('a3','');			    //清空COOKIE数据内容
setcookie('a3','a3',time());	//设定时间戳过期

作用范围:不同的文件夹层级中,设定的 COOKIE 默认是在不同的文件夹下有访问限制。 上层文件夹中设定的 COOKIE 可以在下层(子文件夹)中访问,而子文件夹中设定的 COOKIE 不能在上层文件夹中访问。

  1. 默认(不设定)的范围:就是使用COOKIE默认的作用范围 🌰father.php ```php //访问COOKIE var_dump($_COOKIE);

//设定普通COOKIE setcookie(‘father1’,’father1’);

🍎
![](/files/php/2019-10-28-PHP-15.会话技术-dc06f9f7.png)

2. 设定为 “/” 的含义:告知浏览器当前COOKIE的作用范围是网站根目录 `etcookie (名字,值,生命周期,作用范围)`
🌰son.php
```php
//访问COOKIE
var_dump($_COOKIE);

//设定普通COOKIE
setcookie('son1','son1');

//设定全局访问COOKIE(localhost) 👉 指定路径的 COOKIE , 使 father 也能访问
setcookie('global_son','global_son',0,'/');

🍎

COOKIE跨子域

跨子域:在同一级别域名下,myitcast.com(一级域名),可以有多个子域名(www.myitcast.com和gz.myitcast.com),他们之间是搭建在不同的服务器上(不同文件夹:E:/server/apache/htdocs和E:/web),但是可以通过COOKIE设置实现对应的COOKIE共享访问。但是默认是不允许跨域名访问的。 🌴

  • hosts中增加映射 C:\Windows\System32\drivers\etc\hosts 加入 127.0.0.1 blog.mysite.com
  • Apache24 httpd-vhosts.confC:\fastwork\Apache24\conf\extra\httpd-vhosts.conf
# 再配置一个 blog.mysite.com:80
# 嗯~~主要是用来测 COOKIE跨子域 效果的 👉 setcookie('xxxaa','跨域写入 COOKIE',0,'/','mysite.com');
<VirtualHost *:80>
	DocumentRoot "${SRVROOT}/htdocs"
	ServerName localhost
	<Directory "${SRVROOT}/htdocs">
	Order Deny,Allow
	# Deny from all
	Allow from all
	Options Indexes FollowSymLinks
	DirectoryIndex index.html index.htm index.php
	</Directory>
</VirtualHost>
  1. 设定cookie的有效域名:不同的域名(包含主机)之间不能共享COOKIE
    可以通过setcookie的第五个参数来控制 setcookie(名字,值,生命周期,作用范围,有效域名)
  2. 不设定时的默认有效域名,互不相同
  3. 跨子域的设定方法:在设定域名访问的时候用设定上级域名即可:myitcast.com ,这个是有 所有以 myitcast.com 结尾的网站都可以共享 COOKIE

test.php

echo '<pre>';
var_dump($_COOKIE);

//设定一个本地COOKIE
setcookie('local','local',0,'/');

//指定域名COOKIE
setcookie('消消息','跨域写入COOKIE',time() + 7*24*60*60,'/','mysite.com');//格林威治时间从现在开始7天后过期

🍎 运行结果

设置中查看COOKIE

若改用设置 setcookie('消消息','跨域写入COOKIE',time()+7*24*60*60,'/','www.mysite.com'); 🍎🍎

什么都写不进去…

🐖 必须是同一域名 ‘mysite.com’ 下的子域名才能彼此设置, 比如通过 localhost/test.php 去为 www.mysite.com 增加 COOKIE 则无效 ; 需要使用 blog.mysite.com 进行设置才能成功 。

COOKIE本身只支持简单数据(数字或者字符串),能够保留的数据本身有限,也不成体系。
如果需要使用COOKIE来保留一组数据的化,想办法凑成数组。(COOKIE不支持数组)

  1. 设置形式: setcookie(‘c1[k1]’, 值)
  2. 读取形式: $_ COOKIE[‘c1’][‘k1’]

🌰

//使用“数组”保存COOKIE

//尝试保存数组
//setcookie('goods_ids',array(1,2,3,4,5));
//🍎错误:  Warning: setcookie() expects parameter 2 to be string, array given in C:\fastwork\Apache24\htdocs\test.php on line 6

//伪装数组
setcookie('goods_ids[0]','abcdefghijklmn');
setcookie('goods_ids[1]','小明');
setcookie('goods_ids[2]',2333);
setcookie('goods_ids[3]',66281);

echo '<pre>';
print_r($_COOKIE);

//echo $_COOKIE['goods_ids'][1]; //🍎 小明

🍎
Array
(
  [goods_ids] => Array
      (
          [0] => abcdefghijklmn
          [1] => 小明
          [2] => 2333
          [3] => 66281
      )
)

SESSION

SESSION 原理

Session与浏览器无关,但是与Cookie有关。

  1. PHP碰到session_start()时开启session会话,会自动检测sessionID a) 如果Cookie中存在,使用现成的 b) 如果Cookie中不存在,创建一个sessionID,并通过响应头以Cookie形式保存到浏览器上
  2. 初始化超全局变量 $_ SESSION 为一个空数组
  3. PHP通过 sessionID 去指定位置(session文件存储位置)匹配对应的文件 a) 不存在该文件:创建一个sessionID命名文件 b) 存在该文件:读取文件内容(反序列化),将数据存储到 $_ SESSION 中
  4. 脚本执行结束,将 $_ SESSION 中保存的所有数据序列化存储到 sessionID 对应的文件中

SESSION基本使用

$_ SESSION 是通过 session_start() 函数的调用才会定义的,没有直接定义

  1. 启用 SESSION ,任何时候都需要开启 SESSION (脚本使用到 $_ SESSION 就开启一次)
  2. 设置 SESSION 信息, 如果想存储数据到 SESSION 中,那么只要不断给 $_ SESSION 数组添加元素即可
  3. 读取 SESSION 信息, $_ SESSION 就是一个数组,存储什么数据,什么方式存的,就是可以通过什么方式访问什么数据

🌰

//必须先开启 SESSION,否则报错:
//Notice:  Undefined variable: _SESSION in C:\fastwork\Apache24\htdocs\test.php on line 7  NULL
//var_dump($_SESSION);		


//开启 SESSION
session_start();

//设置 SESSION 数据
$_SESSION['name'] = 'Martin';
$_SESSION['hobby'] = array('basketball','football');

//访问 SESSION 数据
//echo $_SESSION['name'];

echo '<pre>';
print_r($_SESSION);
🍎
Array
(
  [name] => Martin
  [hobby] => Array
      (
        [0] => basketball
        [1] => football
      )

)

会话技术的本质是为了实现跨脚本共享数据:在一个脚本中定义数据,在另外一个脚本中保存数据

🌰在test.php中定义 SESSION 数据 ,在另外的脚本中保存数据

  1. 删除一个SESSION信息 unset($_SESSION['name']); , 删除 SESSION 就是将 SESSION 数据清理掉($_ SESSION拿不到)
  2. 删除全部SESSION信息 $_SESSION = array(); , 删除全部数据就是让 $_ SESSION 变成一个空数组

🌰

echo '<pre>';
session_start();

print_r($_SESSION);

//删除一个SESSION信息
unset($_SESSION['name']);

//删除全部SESSION信息
//$_SESSION = array();

print_r($_SESSION);
🍎删除一个
Array
(
    [name] => Martin
    [hobby] => Array
        (
            [0] => basketball
            [1] => football
        )

)
Array
(
    [hobby] => Array
        (
            [0] => basketball
            [1] => football
        )

)

🍎删除全部
Array
(
    [hobby] => Array
        (
            [0] => basketball
            [1] => football
        )

)
Array
(
)

SESSION 相关配置

SESSION 基础配置 php.ini

  1. session.name :session名字,保存到 COOKIE 中 sessionID 对应的名字 session.name = PHPSESSID
  2. session.auto_start :是否自动开启 session (无需手动 session_start()),默认是关闭的 session.auto_start = 0
  3. session.save_handler :session 数据的保存方式,默认是文件形式 session.save_handler = files
  4. session.save_path:session文件默认存储的位置 , 使用系统的文件夹存储不安全,需要指定对应存储路径
;session.save_path = "/tmp"  👉 session.save_path = "C:\fastwork\Server\Sessions"

SESSION 常用配置

  1. session.cookie_lifetime : PHPsessionID 在浏览器端对应 COOKIE 的生命周期,默认浏览器关闭后会话结束 session.cookie_lifetime = 0
  2. session.cookie_path :sessionID在浏览器存储之后允许服务器访问的路径(COOKIE有作用范围),默认网站根目录 session.cookie_path = /
  3. session.cookie_domain :COOKIE 允许访问的子域(COOKIE可以跨子域), 默认的 PHPsessionID 只能当前主机访问 session.cookie_domain = ,保证数据 的安全

配置的两种形式

  1. php.ini中配置:全局配置,修改php.ini中的配置项 session.save_path = "C:\fastwork\Server\Sessions
  2. 🌈脚本中配置: PHP可以通过 ini_set 函数来在运行中设定某些配置项(只会对当前运行的脚本有效),把这种配置称之为项目级 @ini_set('session.save_path','C:\fastwork\Server\Sessions');

销毁 SESSION

Session删除是指删除session数据,$_ SESSION 中看不到而已;销毁session是指删除session对应的session文件。

系统提供一个函数: session_destroy(),会自动根据 session_start 得到的 sessionID 去找到指定的session文件,并把其删除。

//开启session
session_start();

//删除数据:清空$_SESSION
var_dump($_SESSION);

//测试效果
sleep(5);		//脚本休息5秒执行

//销毁session
session_destroy();

SESSION 垃圾回收机制

垃圾回收机制原理

session会话技术后,session文件并不会自动清除,如果每天有大量session文件产生但是又都是失效的,会增加服务器的压力和影响session效率。
垃圾回收,是指session机制提供了一种解决垃圾session文件的方式:给session文件指定周期,通过session文件最后更改时间与生命周期进行结合判定,如果已经过期则删除对应的session文件,如果没有过期则保留。这样就可以及时清理无效的僵尸文件,从而提升空间利用率和session工作效率。

  1. 任何一次session开启(session_start),session都会尝试去读取session文件
  2. 读取session文件后,有可能触发垃圾回收机制(在session系统中也是一个函数:自己有一定几率调用)
  3. 垃圾回收机制会自动读取所有session文件的最后编辑时间,然后加上生命周期(配置文件)与当前时间进行比较( 所有session文件 ) a) 过期:删除 b) 有效:保留

    垃圾回收参数设置

  4. session.gc_maxlifetime = 1440 :规定的session文件最大的生命周期是1440秒,24分钟
  5. session.gc_probability = 1 :垃圾回收概率因子(分子)
  6. session.gc_divisor = 1000 :垃圾回收概率分母

默认的触发概率是1/1000

🌈php.ini

session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440

测试垃圾回收效果:

  1. 修改生命周期为2分钟,120秒
  2. 修改触发几率:100% 🌰 php.ini
    session.gc_divisor = 1000
    session.gc_maxlifetime = 120
    🍎
    session 文件会很快被删除(回收)
    

禁用COOKIE后如何使用SESSION

禁用COOKIE不能使用SESSION原因 Session技术需要利用到COOKIE技术来保存sessionID,从而使得PHP能够在跨脚本的时候得到相同的sessionID,从而访问同一个session文件。

解决思路:最终让session_start在开启之前拿到原来的sessionID(另外一个脚本的)

实现无COOKIE使用SESSION

在PHP中,想要解决没有COOKIE也实现session技术的方式有两种:

方案1(推荐):可以利用PHP提供的session函数:session_id和session_name来获得和设置sessionID或者name从而解决session_start产生新sessionID的情况(手动操作):

  1. 在session保存数据的脚本中获取sessionID和名字
  2. 想办法将数据传递给另外一个脚本:表单传值(URL或者form表单)
  3. 在需要使用到session的脚本中,先接收数据
  4. 组织session_start产生新的ID,告诉它已经存在:session_id($id)
echo '<pre>';
//开启
session_start();

//获取sessionID和名字
$id = session_id();			//获取是在session_start之后
$name = session_name();		//拿到名字(php.ini session.name)
echo $name . ' = ' . $id . '<br>';

//设置内容
$_SESSION['name'] = 'Changbao';

//传递给另外一个脚本
echo "<a href='test2.php?{$name}={$id}'>click</a>";
🍎
PHPSESSID = 7lhv7dctiksut4trk6aj88urjb
click

另外一个脚本,test2.php

echo '<pre>';
//访问session
//接收数据
$name = session_name();
$id = $_GET[$name];

//⭐ 设定sessionID
session_id($id);

//开启session
session_start();

//访问
var_dump($_SESSION);
🍎 点击 click
array(1) {
  ["name"]=>
  string(8) "Changbao"
}

🐖 session_id() 既可以获取 PHPSESSID 也可以为新的脚本设置 PHPSESSID

方案2:可以利用session集中已经提供的解决方案自动操作(配置)

  • 原因1:默认session配置只允许使用COOKIE保存sessionID:cookie_ony
  • 原因2:默认关闭了其他能够传送数据的方式,只保留了COOKIE
  1. 修改PHP配置文件,开启其他方式传输sessionID,关闭只允许使用COOKIE传输功能
    • session.use_only_cookies = 0 需要关闭,从1变成0
    • session.use_trans_sid = 1 开启其他方式保存sid,从0变成1
  2. 一旦配置开启,PHP会自动将sessionID和session名字在其他位置绑定数据,同时还会在session_start的时候,考虑其他方式传递(表单)的数据,而不是只有COOKIE

对比与方案一的改变:

//保存session数据
session_start();

$_SESSION['age'] = 40;

echo "<a href='40session_nocookie4.php'>click</a>";

test2.php

//访问session数据
session_start();
var_dump($_SESSION);


相关文章

上一篇 14.PHP文件操作

评论