workerman= Worker::$user 配置示例怎么解决?

user_config_demo.php

<?php
/**
 * Workerman Worker::$user 配置示例
 * 演示进程用户配置和安全最佳实践
 */

use Workerman\Worker;

require_once __DIR__ . '/vendor/autoload.php';

// 创建一个 HTTP 服务器
$worker = new Worker('http://0.0.0.0:8080');

// 设置进程数
$worker->count = 4;

// 设置进程名称
$worker->name = 'UserConfigDemo';

// ============================================
// 【Worker::$user 配置】
// ============================================
// 属性: Worker::$user
// 类型: string
// 默认值: 当前用户
//
// 安全说明:
// - 以 root 启动后,子进程切换到此用户运行
// - 降低安全风险
// - 遵循最小权限原则
// - 仅在 Linux/Unix 系统有效,Windows 无效
//
// 使用场景:
// 1. 需要监听 80/443 端口(需 root 启动)
// 2. 生产环境部署提高安全性
// 3. 限制进程权限
// ============================================

// 设置运行用户(取消下面的注释以启用)
// Linux 常用用户: www-data, nobody, www
// $worker->user = 'www-data';

// 启动回调 - 显示当前运行用户
$worker->onWorkerStart = function($worker) {
    // 获取当前用户信息
    $processUser = posix_getpwuid(posix_geteuid());
    $userName = $processUser['name'];
    $userUid = $processUser['uid'];

    echo "========================================\n";
    echo "Worker 进程已启动\n";
    echo "进程ID: " . posix_getpid() . "\n";
    echo "当前用户: {$userName} (UID: {$userUid})\n";
    echo "配置用户: " . ($worker->user ?: '未设置(使用当前用户)') . "\n";
    echo "========================================\n";
};

// HTTP 请求处理
$worker->onMessage = function($connection, $request) {
    // 获取当前进程用户信息
    $processUser = posix_getpwuid(posix_geteuid());

    $response = [
        'message' => 'Worker::$user 配置示例',
        'process_info' => [
            'pid' => posix_getpid(),
            'user' => $processUser['name'],
            'uid' => $processUser['uid'],
            'gid' => $processUser['gid'],
        ],
        'security_note' => [
            '说明' => '以 root 启动后,子进程切换到配置的用户运行',
            '优势' => '降低安全风险,遵循最小权限原则',
            '平台' => 'Linux/Unix 有效,Windows 无效'
        ],
        'usage' => [
            '配置方式' => '$worker->user = "www-data";',
            '启动方式' => 'sudo php user_config_demo.php start',
            '注意事项' => '需要 root 权限启动才能切换用户'
        ]
    ];

    $connection->send(json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
};

// 运行
Worker::runAll();

运行:

启动(查看当前用户)

php user_config_demo.php start

  1. 以 root 权限启动:sudo php user_config_demo.php start

解释:

● Read(user_config_demo.php)
⎿  Read 88 lines

● 📖 完整代码解释

第 1-9 行:引入和初始化

<?php
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';

  • <?php - PHP 开始标签
  • use Workerman\Worker; - 引入 Workerman 的 Worker 类
  • require_once - 加载 Composer 自动加载文件,导入所有依赖库


    第 11-12 行:创建 Worker 实例

    $worker = new Worker('http://0.0.0.0:8080');

    含义:

  • 创建一个 HTTP 服务器
  • http:// - 指定协议为 HTTP
  • 0.0.0.0 - 监听所有网络接口(可从任意IP访问)
  • 8080 - 监听端口号


    第 14-15 行:设置进程数

    $worker->count = 4;

    含义:

  • 启动 4 个子进程来处理请求
  • 每个进程独立运行,可以并行处理多个请求
  • 通常设置为 CPU 核心数,充分利用多核性能


    第 17-18 行:设置进程名称

    $worker->name = 'UserConfigDemo';

    含义:

  • 设置进程名称为 UserConfigDemo
  • 在系统进程列表中(如 ps 命令)会显示这个名称
  • 方便识别和管理进程


    第 20-41 行:Worker::$user 配置说明

    // $worker->user = 'www-data';

    这是核心配置!详细说明:

    属性: Worker::$user
    类型: 字符串(string)
    默认值: 当前启动脚本的用户

    工作原理:

    1. 用 root 用户启动脚本:sudo php user_config_demo.php start
    2. 主进程以 root 运行(需要 root 才能监听特权端口 < 1024)
    3. 子进程自动切换到 $worker->user 指定的用户运行

    安全优势:

  • 降低风险:即使进程被攻击,攻击者也只能获得普通用户权限,无法获得 root 权限
  • 最小权限原则:进程只拥有完成任务所需的最低权限
  • 隔离保护:限制进程对系统文件的访问权限

    使用场景:

    1. 监听特权端口(80/443):需要 root 启动,但子进程降权运行
    2. 生产环境:提高服务器安全性
    3. 权限控制:限制进程只能访问特定目录和文件

    平台限制:

  • ✅ Linux/Unix 系统:完全支持
  • ❌ Windows 系统:不支持(会被忽略)


    第 43-56 行:启动回调函数

    $worker->onWorkerStart = function($worker) {
    $processUser = posix_getpwuid(posix_geteuid());
    $userName = $processUser['name'];
    $userUid = $processUser['uid'];

    echo "当前用户: {$userName} (UID: {$userUid})\n";
    // ...
    };

    含义:

  • onWorkerStart - 当每个子进程启动时触发的回调
  • posix_geteuid() - 获取当前进程的有效用户ID(UID)
  • posix_getpwuid() - 根据UID获取用户详细信息
  • $processUser['name'] - 用户名(如 www-data)
  • $processUser['uid'] - 用户ID(数字,如 33)

    作用:

  • 显示进程启动信息
  • 验证用户切换是否成功
  • 帮助调试和确认配置


    第 58-84 行:HTTP 请求处理

    $worker->onMessage = function($connection, $request) {
    $processUser = posix_getpwuid(posix_geteuid());

    $response = [
    'message' => 'Worker::$user 配置示例',
    'process_info' => [
    'pid' => posix_getpid(), // 进程ID
    'user' => $processUser['name'], // 用户名
    'uid' => $processUser['uid'], // 用户ID
    'gid' => $processUser['gid'], // 组ID
    ],
    // ...
    ];

    $connection->send(json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
    };

    含义:

  • onMessage - 当收到 HTTP 请求时触发
  • $connection - 客户端连接对象
  • $request - HTTP 请求对象
  • posix_getpid() - 获取当前进程ID
  • json_encode() - 将数组转换为 JSON 格式
  • JSON_PRETTY_PRINT - 格式化输出,便于阅读
  • JSON_UNESCAPED_UNICODE - 不转义中文字符
  • $connection->send() - 发送响应给客户端

    返回的信息:

  • 进程信息:PID、运行用户、UID、GID
  • 安全说明:解释 Worker::$user 的作用
  • 使用方法:如何配置和启动


    第 86-87 行:启动 Worker

    Worker::runAll();

    含义:

  • 启动所有 Worker 进程
  • 开始监听端口,等待请求
  • 进入事件循环,持续运行


    🔍 实际运行流程

    1. 普通用户启动(无 Worker::$user 配置)

    php user_config_demo.php start

    流程:

    1. 以当前用户(如 qq230)启动

    2. 主进程和子进程都以 qq230 运行

    3. 访问 http://127.0.0.1:8080/ 显示:
      {
      "process_info": {
      "user": "qq230",
      "uid": 1000
      }
      }

    4. Root 启动 + Worker::$user 配置

    // 取消第 41 行注释
    $worker->user = 'www-data';

    sudo php user_config_demo.php start

    流程:

    1. 以 root 用户启动(UID=0)
    2. 主进程以 root 运行
    3. 子进程自动切换到 www-data 用户运行
    4. 访问 http://127.0.0.1:8080/ 显示:
      {
      "process_info": {
      "user": "www-data",
      "uid": 33
      }
      }

    🛡️ 安全示例对比

    不安全的做法(不推荐)

    所有进程都以 root 运行

    sudo php user_config_demo.php start

    如果被攻击,黑客获得 root 权限!

    安全的做法(推荐)

    $worker->user = 'www-data'; // 配置降权用户
    sudo php user_config_demo.php start

    主进程: root(仅用于启动)

    子进程: www-data(处理请求)

    即使被攻击,黑客只能获得 www-data 权限


    📝 关键函数说明

    函数 作用
    posix_geteuid() 获取当前进程的有效用户ID
    posix_getpwuid($uid) 根据UID获取用户信息数组
    posix_getpid() 获取当前进程ID
    $worker->onWorkerStart 子进程启动时的回调
    $worker->onMessage 收到消息/请求时的回调
    Worker::runAll() 启动所有Worker进程

    完整解释完毕!这个脚本演示了如何安全地配置 Workerman 的进程用户,是生产环境部署的最佳实践。

40 0 0
0个回答

🔝