hyperf 禁用 $_session 是因协程共享内存导致数据竞争,张三可能看到李四的 session 数据;必须通过 composer require hyperf/session 安装组件、启用 sessionmiddleware 中间件,并依赖注入 sessioninterface 调用 set/get 方法安全操作。

Hyperf 里为什么不能直接用 $_SESSION
因为 $_SESSION 是 PHP-FPM 模式下为每个请求单独初始化的全局数组,在 Swoole 协程常驻进程模型中完全不安全。多个协程共享同一块内存,$_SESSION['user_id'] 可能被并发请求互相覆盖——张三登录后看到李四的数据,不是 bug,是必然结果。
Hyperf 启动时根本不会注册 $_SESSION,所以任何地方直接读写都会报 Undefined variable: _SESSION 或静默失败。这不是配置没开,是框架主动禁用。
报错 Class "Hyperf\Session\Session" not found 怎么办
这个错误说明你没装组件,或者装了但没启用中间件。Hyperf 的 Session 功能不是内置的,必须手动引入:
- 运行
composer require hyperf/session - 执行
php bin/hyperf.php vendor:publish hyperf/session生成配置 - 确认
config/autoload/middlewares.php中已启用SessionMiddleware(默认未开启) - 检查
config/autoload/session.php的handler.class是否指向合法驱动类,比如Hyperf\Session\Handler\RedisSessionHandler
用 hyperf/session 替代时最关键的三件事
替代不是“换个写法”,而是切换整套状态管理范式:
- 别再试图在控制器里写
$_SESSION['token'] = $val;改用依赖注入获取SessionInterface实例,调用set()/get() - Session 数据默认不加密,敏感字段如
user_id建议配合encrypt驱动或自行加解密,否则 Cookie 中的 session_id 对应明文数据可被 Redis 管理员窥探 - Redis 驱动要求连接池就绪,如果启动时报
Connection refused,先确认redis.default连接池配置是否正确,且 Redis 服务真实可达(不是 systemd 管理的假 redisd)
容易忽略的兼容性细节
Session ID 默认通过 Cookie 传递,但如果你的接口走 CLI、WebSocket 或跨域请求,Cookie 可能不可用:
- CLI 场景下无法使用 Cookie,需手动传参并调用
$session->setId($id)激活会话 - WebSocket 连接建立后,初始 HTTP 请求带的 Cookie 不会自动延续到后续帧,需在握手阶段提取并绑定
- 前端 fetch 若跨域,要显式设置
credentials: 'include',后端响应头也得有Access-Control-Allow-Credentials: true -
gc_maxlifetime在 Redis 驱动中不起作用,实际过期靠 Redis 的 TTL 控制,务必检查session.gc_lifetime和redis.options.lifetime是否一致
真正麻烦的从来不是“怎么写”,而是“什么时候失效”和“谁能看到”。Hyperf 把 Session 从桌面便签变成了带门禁的保险柜,钥匙(Cookie)和柜子(Redis)都得管好。










