Session简介
Session在网络应用中称为“会话”,在PHP中用于保存用户连续访问web应用时的相关数据,有助于创建高度定制化的程序、增加站点的吸引力。Session通常用于保护用户的登录状态、保存生成的验证码等。故Session在web技术中占有非常重要的地位。
Session是一种服务器端的技术,它的生命周期从用户访问页面开始,直到断开与网络的连接时结束。当PHP启动Session时,Web服务器在运行时会为每个用户的浏览器创建一个供其独享的Session文件。
在创建Session文件时,每个Session都具有一个唯一的会话ID,用于标识不同的用户,且会话ID会分别保存在客户端和服务端两个位置。客户端通过Cookie保存,服务器端则以文件的形式保存到php.ini(Session.save_path指定的目录)指定的Session目录中,对于Windows系统,默认保存到“C:\Windows\Temp”目录中。
Session使用
1、启动
bool session_start()
该函数用于启动Session
2、查看SessionID和Session文件
浏览器在开发者工具中可以查看Cookie保存的会话ID,默认名称为PHPSESSION,在php.ini中配置(session.name)
服务端保存在Session.save_path指定的目录,文件名为“sess_会话ID”的session文件,该文件的会话ID与浏览器的会话ID一致,表示这个文件只允许拥有会话ID的用户访问。
3、Session的使用
通过超全局变量$_SESSION添加、读取或修改Session中的数据。
$_SESSION[]可以删除Session中的所有数据,但Session文件仍然存在,只不过是一个空文件。如果要删除该文件,可以通过session_destroy()函数来实现。
4、Session的配置
在php.ini中配置
配置项 | 含义 |
---|---|
session.name | 指定Cookie的名字,只能由字母组成,默认为PHPSESSID |
session.save_path | 读取或设置当前会话文件的保存路径 |
session.auto_start | 指定是否在请求开始时自动启动一个会话,默认为0(不启动) |
session.cookie_lifetime | 以秒数指定发送到浏览器的Cookie生命周期,默认为0(直到关闭浏览器) |
session.cookie_path | 指定要设定会话Cookie的路径,默认为"/" |
session.cookie_domain | 指定要设定会话Cookie的域名,默认为无 |
session.cookie_secure | 指定是否通过安全连接发送Cookie,默认为off |
session.cookie_httponly | 指定是否仅通过HTTP访问Cookie,默认为off |
注意:
1、在PHP7版本开始,可以在程序中通过session_start()函数的参数对Session进行配置,覆盖php.ini中对应Session配置指令。
如:session_start([‘name’=>‘MySESSID’]);
2、函数接收的是以关联数组形式的参数,数组的键名不包括“session.”,直接书写其后的配置项名称。在修改配置时,session.cookie_lifetime的值是整型,session.auto_start、session.cookie_secure和session.cookie_httponly的值是布尔类型,剩余的配置项均为字符串类型。
3、session_start()函数修改的配置只有在php脚本运行的周期有效,并不影响php.ini的原有配置。
Session机制
默认情况下,PHP中的Session是通过实现SessionHandlerInterface接口,将其以文件的形式存储在服务器中。该接口中有6个抽象方法,分别为close(关闭Session)、destroy(销毁Session)、gc(垃圾回收)、open(开启Session)、read(读取Session)和write(写入Session)
interface SessionHandlerInterface
{
public function close();
public function destory(string $session_id);
public function gc(int $maxlifetime);
public function open(string $save_path,string $session_name);
public function read(string $session_id);
public function write(string $session_id,string $session_data);
}
对于访问量非常大的网站,在服务器中需要存储大量的Session文件,这将影响服务器的响应速度并会带来资源浪费。因此,只要重新实现SessionHandlerInterface接口,完成具体方法的实现,然后再利用PHP提供的Session机制就可以改变Session存储的默认方式。其中,PHP的Session机制是通过session_set_save_handler() 函数实现的,在调用此函数时,可以传递对应的回调函数或类的示例。
用法示例
Session入库
1、创建数据表以保存Session信息
CREATE DATABASE `sess_storage`; # 创建数据库
USE `sess_storage`; # 选择数据库
CREATE TABLE `session` ( # 创建用于保存Session的数据表
`id` VARCHAR(255) PRIMARY KEY COMMENT 'SessionID',
`expires` INT UNSIGNED NOT NULL COMMENT '过期时间',
`data` BLOB COMMENT '数据'
) DEFAULT CHARSET=utf8;
2、实现接口文件SessionDb.php
<?php
class SessionDb implements SessionHandlerInterface
{
private $link; //用于保存数据库连接
/**
* 接口中的open()方法类似于类的构造方法,它会在会话打开的时候被调用
*/
public function open($savePath, $sessionName)
{
$this->link = new mysqli('localhost', 'root', '123456', 'sess_storage');
return (bool) $this->link;
}
/**
* close()类似于类的析构方法,它会在write()方法调用完后被调用
*/
public function close()
{
return $this->link->close();
}
/**
* write()方法用于将Session数据写入到指定位置。默认情况下以文件形式写入服务器中。
*/
public function write($id, $data)
{
$expires = time() + 3600;
$sql = 'REPLACE INTO `session` SET `id` = ?, `expires` =?, `data` = ?';
$stmt = $this->link->prepare($sql);
$stmt->bind_param('sis', $id, $expires, $data);
return (bool) $stmt->execute();
}
/**
* read()方法用于根据Session的会话ID到指定位置获取Session数据并返回执行结果
*/
public function read($id)
{
$now = time();
$sql = "SELECT `data` FROM `session` WHERE `id` = '$id' AND `expires` > $now";
return (string) $this->link->query($sql)->fetch_assoc()['data'];
}
/**
* destory方法用于结束当前会话的同时,根据会话ID删除数据库中对应Session的信息
*/
public function destroy($id)
{
$sql = "DELETE FROM `session` WHERE `id` = $id";
return (bool) $this->link->query($sql);
}
/**
* 接口中的gc()方法用于清理会话中的旧数据,完成垃圾清理
*/
public function gc($maxlifetime)
{
$sql = "DELETE FROM `session` WHERE (`expires` + $maxlifetime ) < $maxlifetime)";
$result = $this->link->query($sql);
return (bool) $result;
}
/**
* 利用SessionDb类的构造方法设置实现Session机制,方法的第一个参数为实现SessionHandlerInterface接口对象,第二个参数设置为true表示将session_write_close()设置为php中止执行时的函数
*/
public function __construct()
{
session_set_save_handler($this, true);
}
}
3、测试文件test.php
<?php
require './SessionDb.php';
new SessionDb(); // 配置Session入库
session_start(); // 启动Session
$_SESSION['test'] = 'content';
4、运行结果