在 PHP 命令行中访问会话?

Posted

技术标签:

【中文标题】在 PHP 命令行中访问会话?【英文标题】:Accessing session in PHP command line? 【发布时间】:2015-07-20 23:43:14 【问题描述】:

我知道命令行不是网络服务器,所以你不能访问$_SESSION。但我不知道还能做什么。

我一直在按照本教程使用 websockets 创建聊天:http://www.phpbuilder.com/articles/application-architecture/optimization/creating-real-time-applications-with-php-and-websockets.html

我的问题是,我不知道如何安全地获取消息发送者的用户名。我可以将它包含在消息发送功能中,但由于它是在 javascript 中,每个人都可以将他们的用户名编辑给其他人。

如何安全地获取用户的用户名$_SESSION['username']

var Server;
Server = new FancyWebSocket('ws://0.0.0.0:9000');
send( "test" );

我愿意接受各种建议,例如 websockets 的替代品。我正在为我的网站创建实时聊天。

【问题讨论】:

HTTP 标头(包括 cookie)在握手期间可供 WS 服务器使用。在该特定服务器中,标头可在属性$headers 下的用户类中以数组形式实现。我稍后会添加一个完整的答案(并添加一个功能请求来解析 cookie),但这应该有助于您朝着正确的方向前进。 【参考方案1】:

当然,第一种选择是 AJAX 请求。 AJAX 不存在无法快速轻松地访问 WebSockets 的会话的问题。任何足够频繁的采样率都无法与实时进行区分。

现在,我在 WebSockets 中实现的相当冗长的解决方案:

在握手期间,WebSocket 服务器可以使用 HTTP 标头,包括 cookie。在您使用的服务器PHP-Websockets 中,标头存储在$headers 属性中。

例如:

var_dump($user->headers);
array(14) 
  ["get"]=>
  string(8) "/echobot"
  ["host"]=>
  string(14) "127.0.0.1:9000"
  ...snip...
  ["cookie"]=>
   string(100) "PHPSESSID=jan9uknpc06mk4ddghph4870t1; MyCookie=My+Value%21%40%23%24%25; MyNonhttponlyCookie=My+Value"

这些 cookie 生成自

session_start();
$_SESSION['Hi!'] = array('Hello!', 'where' => 'world!');
setcookie('MyCookie', 'My Value;!@#$%', 0, '/', '127.0.0.1', false, true);
setcookie('MyNonhttponlyCookie', 'My Value', 0, '/', '127.0.0.1', false, false);

因此,$user->headers['cookie'] 的值是一个分号和空格 (;) 分隔的键值对集合,其中的值经过 URL 编码并用等号与其键分隔。 (如果您在 cookie 名称中放置保留字符,PHP 会报错。因此 cookie 键不能包含任何 url 编码值。)

快速提取这些的方法如下

$cookies = array();
$cookiesParts = explode('; ', $user->headers['cookie']);
foreach ($cookiesParts as $cookieParts) 
    $interimCookie = explode('=', $cookieParts);
    $cookies[$interimCookie[0]] = urldecode($interimCookie[1]);

var_dump($cookies);

array(3) 
  ["PHPSESSID"]=>
  string(26) "jan9uknpc06mk4ddghph4870t1"
  ["MyCookie"]=>
  string(14) "My Value;!@#$%"
  ["MyNonhttponlyCookie"]=>
  string(8) "My Value"

我们现在有了会话 ID。仔细检查session_name(),它将为您提供实际保存会话 ID 的 cookie 的密钥。

我们可以序列化和反序列化存储在服务器中的会话文件,这是由session_save_path() 指向的...但我想作弊。

由于内置的​​会话系统会锁定会话文件,我们不能只保持会话文件打开并不断观察变化,也不能自己长时间锁定文件。

如果我们可以在这里使用__get()__set() 魔术方法就像我们使用$_SESSION 超全局(例如$myUser->_session['key'] = 'value';)一样,那将是理想的,但是PHP 不允许处理这些方法作为数组。相反,我们必须设置一个更普通的命名方法。

<?php
class MyUser extends WebSocketUser 
    public $session_id; // gets set somewhere. Good place is probably is your implementation of the `connected($user)` abstract method.

    public getSession($key) 
        session_id($this->session_id);
        session_start();
        $val = $_SESSION[$key];
        session_write_close(); // very important!
        return $val;
    

    public setSession($key, $value) 
        session_id($this->session_id);
        session_start();
        $_SESSION[$key] = value;
        session_write_close(); // still very important!
    

(注意:我还将我的feature request 指向这个问题,作为我最终实现 cookie 解析和会话处理的基础,以便我在今晚工作时记住我的研究。)

【讨论】:

您好,感谢您的帮助!我真的不知道如何实现和使用 MyUser 类。你能帮帮我吗? FancyWebSocket 类中,您需要将受保护的属性$userClass 指定为新用户类的名称。除此之外,它是基本的 OOP。 对不起,我没有关注你。我没有FancyWebSocket 课程,我有PHPWebSocket 课程。在我的任何文件中都没有名为 $userClass 的内容? @kopa 抱歉,正在查看您在上面共享的 JS 的 sn-p,并假设您将 PHP 类命名为相同,这就是 FancyWebSocket 的来源。当您说您正在关注来自 phpbuilder.com/articles/application-architecture/optimization/… 的教程时……您是指该页面上唯一使用 github.com/ghedipunk/PHP-Websockets 的实际教程吗?或者,您的意思是列出的其他几个备选方案之一? 这看起来确实像是一个有效的 PHP 会话 ID。试一试,看看你会得到什么。

以上是关于在 PHP 命令行中访问会话?的主要内容,如果未能解决你的问题,请参考以下文章

PHP命令行中的换行符

Windows下用cmd命令实例讲解yii2.0在php命令行中运行的步骤

php PHP在命令行中

“php artisan serve”命令在 Laravel 的命令行中不起作用?

PHP 版本在浏览器和命令行中显示不同

php在cli模式下取得命令行中的参数的方法-getopt命令行可传递数组-简单自定义方法取命令行参数