RabbitMQ入门_15_访问控制
参考资料:https://www.rabbitmq.com/access-control.html
A. 核心概念
- Virtual Host:虚拟主机为 RabbitMQ 中的资源提供了逻辑分组与隔离
- 资源:资源是虚拟主机中的实体,例如队列和交换机。不同虚拟主机中的同名实体是不同的资源
## B. Rabbit 访问控制基本流程 当客户端尝试建立到 RabbitMQ 的连接时,必须指定虚拟主机和用户密码。如果用户密码正确,同时该用户在该虚拟主机配置过任何权限,则可以建立连接,否则拒绝连接。
连接建立后,任何对该虚拟主机中资源的操作都会触发权限检查。
C. 权限
RabbitMQ 中每一个资源都对应了三种权限类型:
- configure: 创建与销毁资源
- write:向资源注入消息
- read:从资源获取消息
用户是否拥有某个资源的某种权限类型可以看成是一个最小粒度的权限(这不是官方文档原意,只是个人理解)。
任何对资源的操作,RabbitMQ 都会检查该用户是否有合适的权限。下表列出所有对资源的操作分别需要什么样的权限:
AMQP 0-9-1 Operation | configure | write | read | |
---|---|---|---|---|
exchange.declare | (passive=false) | exchange | ||
exchange.declare | (passive=true) | |||
exchange.declare | (with AE) | exchange | exchange (AE) | exchange |
exchange.delete | exchange | |||
queue.declare | (passive=false) | queue | ||
queue.declare | (passive=true) | |||
queue.declare | (with DLX) | queue | exchange (DLX) | queue |
queue.delete | queue | |||
exchange.bind | exchange (destination) | exchange (source) | ||
exchange.unbind | exchange (destination) | exchange (source) | ||
queue.bind | queue | exchange | ||
queue.unbind | queue | exchange | ||
basic.publish | exchange | |||
basic.get | queue | |||
basic.consume | queue | |||
queue.purge | queue |
例如第5行的 queue.declare (passive=false) 操作,即之前我们调用的 senderChannel.queueDeclare("test", true, false, false, null);
,它要求用户对 test 队列(资源)有 configure 操作权限。如果没有该权限,申明队列的请求会抛出异常,哪怕该队列实际已经存在都不行。
而根据第6行,哪怕用户对 test 队列没有任何权限,也可以通过 senderChannel.queueDeclarePassive("test");
申明该队列。(当然,就算不申明,该队列也是可以直接使用的。passive 方式的申明只是用来判断队列是否已经存在)
D. 设置权限
https://www.rabbitmq.com/man/rabbitmqctl.1.man.html#Access control
通过 rabbitmqctl 的 set_permissions 命令可以为用户设置权限,命令格式为:
set_permissions [-p vhost] {user} {conf} {write} {read}
- vhost:虚拟主机的名字,默认的虚拟主机是 "/"。
- user:用户名
- conf:一个正则表达式,用户对符合该正则表达式的所有资源拥有 configure 操作的权限
- write:一个正则表达式,用户对符合该正则表达式的所有资源拥有 write 操作的权限
- read:一个正则表达式,用户对符合该正则表达式的所有资源拥有 read 操作的权限
实例:`rabbitmqctl set_permissions -p /myvhost test "^test-.*" ".*" ".*"` 为 test 用户在 /myvhost 虚拟主机中设置以下权限:对 test- 开头的资源赋予 configure 权限,对所有资源赋予 write 和 read 权限。
显然,一个用户对一个虚拟主机只能设置一条权限配置,这对正则表达式的定义提出了要求,也对资源命名规则提出了要求。
E. 实战
本文涉及的所有功能都可以通过管理插件在管理页面操作。
我们将创建 test 用户,使其可以访问 /test 虚拟主机,同时对 /test 虚拟主机中名字为 hello 的资源具有 configure 权限,所有资源具有 write 和 read 权限:
- 在管理页面 Admin > Users 页创建用户 test
- 在管理页面 Admin > Virtual Hosts 页创建虚拟主机 /test
- 在虚拟主机列表中点击 /test 虚拟主机,进入详细信息页面
- 在 Permissions 区段中选择 test 用户,将 Configure regexp 设置为 hello,其它不变,点击 Set permission 按钮
**gordon.study.rabbitmq.accesscontrol.TestAccessControl.java**
public class TestAccessControl {
private static final String QUEUE_NAME = "test";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setVirtualHost("/test");
factory.setUsername("test");
factory.setPassword("test123");
Connection connection = factory.newConnection();
Channel senderChannel = connection.createChannel();
// senderChannel.queueDeclare(QUEUE_NAME, true, false, false, null); // throw Exception
senderChannel.queueDeclarePassive(QUEUE_NAME);
senderChannel.basicPublish("", QUEUE_NAME, null, "test".getBytes("UTF-8"));
}
}