Skip to content

RabbitMQ 权限管理

一、概述

RabbitMQ 权限管理通过细粒度的访问控制,确保用户只能访问其被授权的资源。正确配置权限是保护消息系统安全的重要组成部分。

权限管理架构

mermaid
graph TB
    A[用户] --> B[虚拟主机]
    B --> C{权限检查}
    C --> D[配置权限]
    C --> E[写入权限]
    C --> F[读取权限]
    
    D --> G[队列/交换器操作]
    E --> H[发布消息]
    F --> I[消费消息]

二、核心知识点

2.1 权限类型

权限类型说明操作
configure配置权限创建/删除队列、交换器
write写入权限发布消息、绑定操作
read读取权限消费消息、获取消息

2.2 权限范围

mermaid
graph TB
    A[权限范围] --> B[虚拟主机]
    B --> C[资源模式]
    C --> D[具体资源]
    
    B --> B1[/]
    B --> B2[/production]
    B --> B3[/development]
    
    C --> C1[".* 所有资源"]
    C --> C2["^order\\. 订单相关"]
    C --> C3["^user\\. 用户相关"]

2.3 权限配置语法

bash
# 设置权限命令
rabbitmqctl set_permissions [-p vhost] user configure write read

# 示例
rabbitmqctl set_permissions -p /production app_user "^order\." "^order\." "^order\."

2.4 默认权限

用户默认权限
guest/ 虚拟主机完全权限
新用户无权限

三、配置示例

3.1 基本权限配置

bash
# 创建用户
rabbitmqctl add_user app_user password123

# 设置用户标签
rabbitmqctl set_user_tags app_user monitoring

# 授予虚拟主机权限
rabbitmqctl set_permissions -p /production app_user ".*" ".*" ".*"

# 授予特定资源权限
rabbitmqctl set_permissions -p /production order_service \
    "^order\." "^order\." "^order\."

# 清除权限
rabbitmqctl clear_permissions -p /production app_user

# 查看权限
rabbitmqctl list_permissions -p /production
rabbitmqctl list_user_permissions app_user

3.2 虚拟主机管理

bash
# 创建虚拟主机
rabbitmqctl add_vhost /production
rabbitmqctl add_vhost /development

# 删除虚拟主机
rabbitmqctl delete_vhost /development

# 列出虚拟主机
rabbitmqctl list_vhosts

# 设置虚拟主机限制
rabbitmqctl set_vhost_limits -p /production '{"max-connections":1000}'
rabbitmqctl set_vhost_limits -p /production '{"max-queues":10000}'

3.3 PHP 权限管理

php
<?php

class PermissionManager
{
    private string $host;
    private int $port;
    private string $user;
    private string $password;
    
    public function __construct(
        string $host = 'localhost',
        int $port = 15672,
        string $user = 'guest',
        string $password = 'guest'
    ) {
        $this->host = $host;
        $this->port = $port;
        $this->user = $user;
        $this->password = $password;
    }
    
    private function request(string $endpoint, string $method = 'GET', array $data = null): array
    {
        $url = "http://{$this->host}:{$this->port}/api/{$endpoint}";
        
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_USERPWD => "{$this->user}:{$this->password}",
            CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
            CURLOPT_CUSTOMREQUEST => $method,
        ]);
        
        if ($data !== null) {
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        }
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        
        return [
            'status' => $httpCode,
            'data' => json_decode($response, true)
        ];
    }
    
    public function setPermission(
        string $vhost,
        string $username,
        string $configure,
        string $write,
        string $read
    ): array {
        return $this->request("permissions/{$vhost}/{$username}", 'PUT', [
            'configure' => $configure,
            'write' => $write,
            'read' => $read,
        ]);
    }
    
    public function deletePermission(string $vhost, string $username): array
    {
        return $this->request("permissions/{$vhost}/{$username}", 'DELETE');
    }
    
    public function listPermissions(string $vhost = '%2f'): array
    {
        return $this->request("vhosts/{$vhost}/permissions");
    }
    
    public function listUserPermissions(string $username): array
    {
        return $this->request("users/{$username}/permissions");
    }
    
    public function createVhost(string $name): array
    {
        return $this->request("vhosts/{$name}", 'PUT');
    }
    
    public function deleteVhost(string $name): array
    {
        return $this->request("vhosts/{$name}", 'DELETE');
    }
    
    public function listVhosts(): array
    {
        return $this->request('vhosts');
    }
    
    public function setVhostLimits(string $vhost, int $maxConnections = null, int $maxQueues = null): array
    {
        $limits = [];
        if ($maxConnections !== null) {
            $limits['max-connections'] = $maxConnections;
        }
        if ($maxQueues !== null) {
            $limits['max-queues'] = $maxQueues;
        }
        
        return $this->request("vhost-limits/{$vhost}/set", 'POST', $limits);
    }
    
    public function generatePermissionReport(): string
    {
        $vhosts = $this->listVhosts();
        
        $report = "=== RabbitMQ 权限报告 ===\n";
        $report .= "时间: " . date('Y-m-d H:i:s') . "\n\n";
        
        foreach ($vhosts['data'] ?? [] as $vhost) {
            $name = $vhost['name'];
            $report .= "虚拟主机: {$name}\n";
            
            $permissions = $this->listPermissions($name === '/' ? '%2f' : $name);
            
            foreach ($permissions['data'] ?? [] as $perm) {
                $report .= "  用户: {$perm['user']}\n";
                $report .= "    配置: {$perm['configure']}\n";
                $report .= "    写入: {$perm['write']}\n";
                $report .= "    读取: {$perm['read']}\n\n";
            }
        }
        
        return $report;
    }
    
    public function auditPermissions(): array
    {
        $vhosts = $this->listVhosts();
        $issues = [];
        
        foreach ($vhosts['data'] ?? [] as $vhost) {
            $name = $vhost['name'];
            $permissions = $this->listPermissions($name === '/' ? '%2f' : $name);
            
            foreach ($permissions['data'] ?? [] as $perm) {
                if ($perm['configure'] === '.*' && $perm['write'] === '.*' && $perm['read'] === '.*') {
                    $issues[] = [
                        'vhost' => $name,
                        'user' => $perm['user'],
                        'issue' => '拥有完全权限',
                        'severity' => 'warning',
                    ];
                }
            }
        }
        
        return [
            'timestamp' => date('Y-m-d H:i:s'),
            'total_issues' => count($issues),
            'issues' => $issues,
        ];
    }
}

$manager = new PermissionManager('localhost', 15672, 'admin', 'Admin@123456');

// 创建虚拟主机
$manager->createVhost('production');

// 设置权限
$manager->setPermission('production', 'app_user', '^order\.', '^order\.', '^order\.');

// 生成报告
echo $manager->generatePermissionReport();

// 审计权限
$audit = $manager->auditPermissions();
echo "\n=== 权限审计 ===\n";
echo "问题数: {$audit['total_issues']}\n";
foreach ($audit['issues'] as $issue) {
    echo "  [{$issue['severity']}] {$issue['user']}@{$issue['vhost']}: {$issue['issue']}\n";
}

四、常见问题与解决方案

4.1 权限不足

问题: 用户无法访问资源

排查:

bash
# 查看用户权限
rabbitmqctl list_user_permissions username

# 查看虚拟主机权限
rabbitmqctl list_permissions -p /vhost

# 检查资源名称是否匹配权限模式
rabbitmqctl list_queues name

4.2 虚拟主机限制

问题: 无法创建更多队列或连接

解决方案:

bash
# 查看限制
rabbitmqctl list_vhost_limits

# 移除限制
rabbitmqctl clear_vhost_limits -p /vhost

五、最佳实践建议

5.1 权限设计

  1. 最小权限原则: 只授予必要的权限
  2. 资源隔离: 使用虚拟主机隔离不同应用
  3. 命名规范: 使用统一的前缀命名资源

5.2 权限模板

php
<?php

class PermissionTemplates
{
    public static function getTemplates(): array
    {
        return [
            'admin' => [
                'configure' => '.*',
                'write' => '.*',
                'read' => '.*',
            ],
            'producer' => [
                'configure' => '^app\.',
                'write' => '.*',
                'read' => '^app\.reply\.',
            ],
            'consumer' => [
                'configure' => '^app\.reply\.',
                'write' => '^app\.reply\.',
                'read' => '^app\.',
            ],
            'monitoring' => [
                'configure' => '',
                'write' => '',
                'read' => '.*',
            ],
        ];
    }
}

六、相关链接