RabbitMQ只允许用户绑定、声明和使用队列



我正在尝试了解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.declarequeue.bindqueue.unbindbasic.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等将只具有只读权限。

  1. 创建将发布消息并对所有内容都有权限的用户(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 ".*" ".*" ".*"
    
  2. 让那个用户(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);
    
  3. 创建只能从这些队列中读取的用户(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.*)"
    
  4. 现在是发布消息的用户(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);
    }
    
  5. 以下是接收这些消息的消费者(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);
    };
    

最新更新