我正在尝试了解RabbitMQ上的权限;因此,我正在阅读这篇文章:
https://www.rabbitmq.com/access-control.html#authorisation
我第一次将我的用户创建为
rabbitmqctl add_user MyUser MyPassword
然后我允许该用户作为
rabbitmqctl set_permissions -p / MyUser ".*" ".*" ".*"
这很好,用户可以做任何事情。现在我想限制权限。
我试图构建的(你可以跳过这部分(:
我需要构建一个应用程序,它可以将消息发布到多个订阅者。为此,我使用了RabbitMQ,它非常有效。换句话说,假设我有电脑A、B、C和D服务器A发布一条消息供B、C和D接收通过创建一个通过FanoutExchange。然后,每个订阅者(使用者(创建一个队列,并将其绑定到FanoutExchange。每次计算机A发布消息后,每个订阅者都会得到相同的消息这很好,但现在我想阻止计算机B、C和D发布消息
如何创建一个只能使用queue.declare
、queue.bind
、queue.unbind
和basic.consume
的用户?
这就是我尝试过的:
# this does not work because MyUser is able to publish messages to a queue
rabbitmqctl set_permissions -p / MyUser "(queue*)" ".*" ".*"
# this does not work. MyUser is not able to bind or declare the queue
rabbitmqctl set_permissions -p / MyUser "(queue.bind*|queue.declare*)" ".*" ".*"
# error message I get when trying to bind the queue on my code is:
# operation queue.declare caused a channel exception access_refused: access to queue 'test-fanout-queue-a' in vhost '/' refused for user 'MyUser'
# tried giving the user readonly permissions but that does not work because a queue has to be created
rabbitmqctl set_permissions -p / MyUser ".*" "^$" ".*"
有人能帮助我使用命令行创建正确的权限吗?或者有人能帮我找到一个不错的教程吗。文档很难理解,也没有提供有用的示例。
终于找到了解决方案。如果有人有更好的,请张贴它,因为我不喜欢这个解决方案哈哈。
在本例中,user_a拥有执行所有操作的权限。而user_b、user_c等将只具有只读权限。
-
创建将发布消息并对所有内容都有权限的用户(user_a(
# this is bash script rabbitmqctl add_user user_a password_a # give it permissions to do everything rabbitmqctl set_permissions -p / user_a ".*" ".*" ".*"
-
让那个用户(user_a(提前创建队列和绑定,因为其他用户没有权限这样做
// This is created in dotnet c#. Hopefully you can get the idea string exchangeName = "my-exchange"; var factory = new ConnectionFactory() { HostName = "localhost", UserName = "user_a", Password = "password_a" }; using var connection = factory.CreateConnection(); using var channel = connection.CreateModel(); // create the exchange that will persist. channel.ExchangeDeclare(exchangeName, ExchangeType.Fanout, durable: true, autoDelete: false); // create 4 queues with this settings because user_b will not have access to create these channel.QueueDeclare("queue-1", durable: true, exclusive: false, autoDelete: false); channel.QueueDeclare("queue-2", durable: true, exclusive: false, autoDelete: false); channel.QueueDeclare("queue-3", durable: true, exclusive: false, autoDelete: false); channel.QueueDeclare("queue-4", durable: true, exclusive: false, autoDelete: false); // bind this 4 queues to that exchange (maybe this is not needed) channel.QueueBind("queue-1", exchangeName, string.Empty); channel.QueueBind("queue-2", exchangeName, string.Empty); channel.QueueBind("queue-3", exchangeName, string.Empty); channel.QueueBind("queue-4", exchangeName, string.Empty);
-
创建只能从这些队列中读取的用户(user_b(。
# this is bash script # create user rabbitmqctl add_user user_b password_b # set its permissions rabbitmqctl set_permissions -p / c "queue.*" "(queue.*)" "(my-exchange.*|queue.*)"
-
现在是发布消息的用户(user_a(的c#代码:
string exchangeName = "my-exchange"; var factory = new ConnectionFactory() { HostName = "localhost", UserName = "user_a", Password = "password_a" }; using var connection = factory.CreateConnection(); using var channel = connection.CreateModel(); // publish one thousand messages for (int i = 1; i < 1000; i++) { var message = new { Name = "Producer", Message = $"Hello Fanout {i}" }; var json = System.Text.Json.JsonSerializer.Serialize(message); var bodyBinary = Encoding.UTF8.GetBytes(json); channel.BasicPublish(exchangeName, string.Empty, null, bodyBinary); Thread.Sleep(1000); }
-
以下是接收这些消息的消费者(user_b(的代码
string exchangeName = "my-exchange"; string queueName = "queue-1"; var factory = new ConnectionFactory() { // connection string if using an uri // amqp://lh:guiest@localhost:5672 HostName = "localhost", UserName = "user_b", Password = "password_b" // TODO in the future use SSL because connection is remote // Port = 5671, //Ssl = new SslOption() { ... } }; using var connection = factory.CreateConnection(); using var channel = connection.CreateModel(); // bind to queue channel.QueueBind(queueName, exchangeName, string.Empty); var consumer = new EventingBasicConsumer(channel); consumer.Received += (sender, args) => { var body = args.Body.ToArray(); var message = Encoding.UTF8.GetString(body); Console.WriteLine(message); };