【问题标题】:PHP SESSION not working in websocket serverPHP SESSION 在 websocket 服务器中不起作用
【发布时间】:2026-01-14 12:40:01
【问题描述】:

我有一个简单的 PHP websocket 用于实时聊天应用程序。我使用 apache 服务器和 websocket 服务器。

当用户名登录成功时,我在 login.php 中将 SESSION 设置为用户名,如下所示

@session_start();
$_SESSION["user"] = $username;

我必须通过 php server.php 启动 websocket 服务器。

因此,即使我开始会话,我也无法获得 $_SESSION["user"] 的值。 作为未定义的索引用户,我给出了一个错误。

【问题讨论】:

  • 你有 session_start();在 server.php 中?
  • 是的,我确实使用 session_start() 开始了会话;
  • 确保session_save_path()session_name() 是相同的,无论您是通过Web 还是通过CLI 访问它。另外,最重要的是,不要忘记经常运行session_write_close();尤其是在 WebSocket 服务器中。

标签: php apache session websocket


【解决方案1】:

会话 ID 在 cookie 中可用,通常命名为 PHPSESSID(取决于 session.name php.ini 设置,并且可以在执行期间使用 session_name() 进行检查和更改。

当用户连接时,WebSocket 服务器可以使用 HTTP 标头,包括 cookie。负责的 WS 服务器应该存储这些标头,并通过用户对象(或连接对象,或任何对象存储和唯一标识将消息发送回连接的资源)提供给应用程序客户)。

另外,请注意 PHP 会话系统会在用户会话打开时锁定它。因为 WebSocket 服务器被设计为连续运行,所以它们永远不会自行解锁会话。

因此,如果用户的会话在 WS 中打开,那么每个 AJAX 和正常 Web 请求都会超时。该用户将根本无法使用您的网站。

此外,一次只能在脚本中打开一个会话。如果第二个用户连接到 WS 服务器,则该用户将有权访问第一个用户的所有会话信息,而无法访问他们自己的会话。 (有点像一个巨大的、巨大的、巨大的安全漏洞。)

因此,如果您打开会话,您必须尽快使用 session_write_close() 关闭会话。

请参阅this previous question 并回答 WebSocket 服务器中会话的特定实现,作为在您的实现中查找内容的示例。 (注意:有些人可能会想把这个问题称为重复问题。虽然我希望这两个问题都保持活跃,但我认为,这里的这个问题应该是一个站得住脚的问题,因为它更笼统(不涵盖一个特定的 WS 服务器),并且由于该 WS 服务器的积极开发,最后一个问题中给出的建议很快就会过时。)

【讨论】:

  • Web 套接字需要更多工作。所有这一切似乎真的很 hacky,也许 apache 的专用 Web 套接字服务器会做到这一点。
  • @Alex_Nabu:Apache 的 Web 服务器将是错误的选择,因为 HTTP 流量和 WebSocket 流量是完全不同的范例。使用与应用程序相同的语言编写的 WebSocket 服务器确实是最佳选择,尤其是因为无法将类似 CGI 的接口放入 WS 连接(这是 Web 服务器处理向 PHP 发送 Web 流量请求的方式)。 -- 缺点和技巧都完全落在 PHP 的肩上,但是任何语言都会有它自己的问题,除非像 WS 这样的东西被明确地设计到语言中。
  • 我只是想更多地遵循标准化。使 Web 开发成为最大的开发社区的原因之一是有一种事实上的标准方式来完成所有事情。 Websockets 有点改变了这一点。 TBH 考虑到你可以用任何你想要的语言做一个套接字服务器,现在甚至没有任何理由使用 php。我的意思是应该有一些流行的实现来标准化我们在处理 Web 套接字时如何做事。在 apache/nginx 等下工作时,一些流行的 lib 可以让事情变得简单而简单,就像 php 所做的那样
  • @Alex_Nabu:现在,最大的两个是 Ratchet 和我自己的 PHP-Websockets,类似于 Linux 上的两大 Web 服务器是 Apache HTTPd 和 nginx。 (Google 也有一个非常简单的 WebSocket 类示例,但这已经与 Tim Berners-Lee 的 Web 服务器不同了。)还有许多其他平台的 WebSocket 服务器,例如用于 Node.js 应用程序的 Socket.io,但是它们与 .NET 和 IIS 一样邪恶和毒瘤.
【解决方案2】:

但是,可以启动与 Apache 服务器的会话,然后在 websocket 代码中访问会话 cookie。

Apache 服务器的文件启动会话。您可以在每次向 websocket 服务器发送新消息时发送会话 id,并且您可以轻松地使用会话 id 检查会话。

看这个:

session_id("your session_id");    
session_start();
if(isset($_SESSION["SESSION_NAME"])){
     //keep connected and process request
}
else{
     //disconnect
}

您可以从here查看逐步示例。

【讨论】:

    【解决方案3】:

    PHP 文档中的某个人非常疯狂地尝试这样做(我的回答来自那个人)

    但基本上,为了让您在基于当前 Web 的命令行之间切换,您需要从 Web 获取当前会话 ID 并将其设置回 cli。

    Write_session.php

    <?php
    
    session_start();
    $_SESSION['test']='test';
    
    print_r($_SESSION);
    
    echo session_id();
    
    ?>
    

    write_session.php 的输出

    gqptpc3scf4k0h3vpl2d341u13
    

    Read_session.php(我想你需要找到一种安全的方式来发送会话 ID)

    <?php
    
    $ssid = "gqptpc3scf4k0h3vpl2d341u13";
    
    session_id ($ssid);
    session_start();
    
    print_r($_SESSION);
    
    ?>
    

    参考:http://php.net/manual/en/function.session-start.php#53293

    【讨论】:

    • 我仍然无法在 server.php 中获取 SESSION。我在 login.php 中设置 SESSION["username"] 既不是 COOKIE。它的空白数组。还有其他解决方案吗?