SessionHandlerInterface 类

(PHP 5 >= 5.4.0, PHP 7, PHP 8)

简介

SessionHandlerInterface 是一个接口,它定义了创建自定义会话处理程序的最小原型。为了将自定义会话处理程序传递给 session_set_save_handler() 使用其 OOP 调用,该类可以实现此接口。

请注意,此类的回调方法旨在由 PHP 内部调用,不打算从用户空间代码调用。

接口概要

interface SessionHandlerInterface {
/* 方法 */
public close(): bool
public destroy(string $id): bool
public gc(int $max_lifetime): int|false
public open(string $path, string $name): bool
public read(string $id): string|false
public write(string $id, string $data): bool
}

示例

示例 #1 使用 SessionHandlerInterface 的示例

以下示例提供基于文件的会话存储,类似于 PHP 会话的默认保存处理程序 files。此示例可以轻松扩展以使用您最喜欢的 PHP 支持的数据库引擎覆盖数据库存储。

注意,我们使用 session_set_save_handler() 的 OOP 原型并使用该函数的参数标志注册关闭函数。这通常在将对象注册为会话保存处理程序时建议。

警告

为了简洁起见,此示例省略了输入验证。但是,$id 参数实际上是用户提供的价值观,需要适当的验证/清理以避免漏洞,例如路径遍历问题。因此,请勿在生产环境中使用此示例的未修改版本。

<?php
class MySessionHandler implements SessionHandlerInterface
{
private
$savePath;

public function
open($savePath, $sessionName): bool
{
$this->savePath = $savePath;
if (!
is_dir($this->savePath)) {
mkdir($this->savePath, 0777);
}

return
true;
}

public function
close(): bool
{
return
true;
}

#[
\ReturnTypeWillChange]
public function
read($id)
{
return (string)@
file_get_contents("$this->savePath/sess_$id");
}

public function
write($id, $data): bool
{
return
file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true;
}

public function
destroy($id): bool
{
$file = "$this->savePath/sess_$id";
if (
file_exists($file)) {
unlink($file);
}

return
true;
}

#[
\ReturnTypeWillChange]
public function
gc($maxlifetime)
{
foreach (
glob("$this->savePath/sess_*") as $file) {
if (
filemtime($file) + $maxlifetime < time() && file_exists($file)) {
unlink($file);
}
}

return
true;
}
}

$handler = new MySessionHandler();
session_set_save_handler($handler, true);
session_start();

// 继续通过 $_SESSION 的键设置和检索值

目录

添加笔记

用户贡献笔记 8 notes

ohcc at 163 dot com
6 年前
从 PHP 7.0 开始,您可以实现 SessionUpdateTimestampHandlerInterface 来
定义您自己的会话 ID 验证方法,例如 session_set_save_handler() 的非 OOP 原型中的 validate_sid 和时间戳更新方法,例如 update_timestamp。

SessionUpdateTimestampHandlerInterface 是 PHP 7.0 中引入的一个新接口,尚未记录。它有两个抽象方法:SessionUpdateTimestampHandlerInterface :: validateId($sessionId) 和 SessionUpdateTimestampHandlerInterface :: updateTimestamp($sessionId, $sessionData)。

<?php
/*
@author Wu Xiancheng
仅供 PHP 7.0+ 使用的代码结构,因为 SessionUpdateTimestampHandlerInterface 是在 PHP 7.0 中引入的
使用此类,您可以验证 php 会话 ID 并更新 php 会话数据的时间戳
使用 PHP 7.0+ 中 session_set_save_handler() 的 OOP 原型
*/
class PHPSessionXHandler implements SessionHandlerInterface, SessionUpdateTimestampHandlerInterface {
public function
close(){
// 返回值应为成功时的 true 或失败时的 false
// ...
}
public function
destroy($sessionId){
// 返回值应为成功时的 true 或失败时的 false
// ...
}
public function
gc($maximumLifetime){
// 返回值应为成功时的 true 或失败时的 false
// ...
}
public function
open($sessionSavePath, $sessionName){
// 返回值应为成功时的 true 或失败时的 false
// ...
}
public function
read($sessionId){
// 返回值应为会话数据或空字符串
// ...
}
public function
write($sessionId, $sessionData){
// 返回值应为成功时的 true 或失败时的 false
// ...
}
public function
create_sid(){
// 自 PHP 5.5.1 起可用
// 在需要新的会话 ID 时在内部调用
// 不需要参数,返回值应为创建的新的会话 ID
// ...
}
public function
validateId($sessionId){
// 实现 SessionUpdateTimestampHandlerInterface::validateId()
// 自 PHP 7.0 起可用
// 返回值应为会话 ID 有效时的 true,否则为 false
// 如果返回 false,php 将在内部生成一个新的会话 ID
// ...
}
public function
updateTimestamp($sessionId, $sessionData){
// 实现 SessionUpdateTimestampHandlerInterface::validateId()
// 自 PHP 7.0 起可用
// 返回值应为成功时的 true 或失败时的 false
// ...
}
}
?>
ohcc at 163 dot com
6 年前
session_set_save_handler() 的非 OOP 原型从 PHP 7.0 开始支持 validate_sid 和 update_timestamp,而 OOP 原型即使在 PHP 7.2 中也不支持。但是 OOP 原型从 PHP 5.5.1 开始支持 create_sid。

validate_sid($sessionId)
此回调用于验证 $sessionId。它的返回值应为有效的会话 ID $sessionId 为 true,无效的会话 ID $sessionId 为 false。如果返回 false,则会生成一个新的会话 ID 来替换无效的会话 ID $sessionId。

update_timestamp($sessionId)
此回调用于更新时间戳,其返回值应为成功时的 true 或失败时的 false。
ohcc at 163 dot com
6 年前
从 PHP 5.5.1 开始,支持另一种方法 create_sid()。当调用 session_regenerate_id() 时,将调用它。

SessionHandlerInterface {
/* 方法 */
abstract public bool close ( void )
abstract public bool create_sid ( void )
abstract public bool destroy ( string $session_id )
abstract public bool gc ( int $maxlifetime )
abstract public bool open ( string $save_path , string $session_name )
abstract public string read ( string $session_id )
abstract public bool write ( string $session_id , string $session_data )
}
avenidagez at foro5 dot com
9 年前
请注意,session_start( ) 会先调用 open,然后调用 read,并且类对 open 返回 true,对 read 返回会话值或空值。
好吧,那么没有捕获错误,也就是说,session_start() 必须在失败时返回 false,但对于类在 open 方法上的实现情况并非如此,无论您从 open 返回 true、false 或任何其他值,都会被 session_start() 函数忽略,并继续执行 read 方法
一个错误?如果 open 返回 false,session_start() 应该停止下一步(read)并返回自身的 false

if(session_start()) ...code
else exit( );

所以忘记 session_start() 的返回值吧,您需要实现一个错误捕获例程并在 open 方法失败时退出()
warxcell at gmail dot com
11 年前
您应该在类名前面加上 <b>\</b>,以告诉 php 它来自根命名空间。
tony at marston-home dot demon dot co dot uk
6 年前
您的自定义会话处理程序不应包含对任何会话函数的调用,例如 session_name() 或 session_id(),因为相关值作为参数传递给各种处理程序方法。尝试从其他来源获取值可能无法按预期工作。
ohcc at 163 dot com
4 年前
如果您想在自己的会话处理类中使用类型声明,请不要“实现”SessionHandlerInterface、SessionIdInterface 或 SessinUpdateTimestampInterface,否则您将收到一个致命错误,指出类方法的声明必须与接口方法兼容。

一个不好的例子
<?php
class SessionWuXianchengHandler implements SessionHandlerInterface {
public function
open(string $sessionPath, string $sessionName) : bool {
}
......
}
?>

一个好的例子
<?php
class SessionWuXianchengHandler {
public function
open(string $sessionPath, string $sessionName) : bool {
}
......
}
?>
StanE
8 年前
我认为 MySessionHandler 类在 gc() 方法中的示例存在一个小“错误”。它使用了 filemtime() 函数,其返回值被 PHP 缓存。在 gc() 方法的 foreach 块中添加以下行

clearstatcache(true, $file);
To Top