upscale/swoole-session

PHP会话与Swoole Web服务器的兼容性

2.1.0 2023-06-12 20:07 UTC

This package is auto-updated.

Last update: 2024-08-28 08:03:24 UTC


README

此库实现了原生PHP会话与Swoole / Open Swoole Web服务器之间的兼容性。

功能

  • 透明的会话开始/停止
  • 会话ID存储在cookie或查询字符串中
  • 原生或自定义会话ID生成器
  • 自动会话数据持久化
  • 符合PHP会话配置

安装

该库通过Composer作为依赖项安装

composer require upscale/swoole-session

用法

将请求处理中间件包装到会话装饰器中

require 'vendor/autoload.php';

use Upscale\Swoole\Session\SessionDecorator;

$server = new \Swoole\Http\Server('127.0.0.1', 8080);
$server->set([
    // Disable coroutines to safely access $_SESSION
    'enable_coroutine' => false,
]);
$server->on('request', new SessionDecorator(function ($request, $response) {
    $_SESSION['data'] ??= rand();
    $response->end($_SESSION['data']);
}));

$server->start();

限制

协程

PHP会话依赖于超全局变量$_SESSION,因此与Swoole协程不兼容。当请求空闲进行异步I/O操作时,其工作进程被重新用于处理其他请求。Swoole切换调用栈上下文,但超全局变量保留在协程/请求之间共享的内存中。为某个请求加载的会话数据泄漏到其他请求,导致各种数据完整性问题。

为了安全使用PHP会话,请禁用协程

$server->set([
    'enable_coroutine' => false,
]);

输出

Swoole环境中禁止直接输出绕过响应实例\Swoole\Http\Response。写入标准输出流违反了PHP会话函数的headers_sent要求

PHP警告:session_start(): 当headers已经发送时无法启动会话

发送headers的语句会阻碍会话

  • echo/print
  • fwrite(STDOUT)
  • file_put_contents('php://stdout')
  • include 'template.phtml'
  • header()
  • setcookie/setrawcookie()
  • 等等。

输出缓冲通常由模板引擎使用,以避免这种陷阱,例如

ob_start();
include $templatePhtml;
$output = ob_get_clean();

$response->end($output);

警告! 在Swoole 4.5.3之前,即使启用了输出缓冲,也会使用协程发送headers。由于上述数据完整性的原因,必须禁用协程,因此这不是问题。

阻塞

并发请求容易受到会话写竞争条件的影响。PHP默认基于文件的会话存储使用文件系统锁定来避免数据损坏。具有相同会话ID的请求依次执行,阻止它们各自的工作进程从session_start()阻塞到session_write_close()

专为Swoole构建的异步协程感知库

许可

Apache License, Version 2.0下许可。