參考 http://blog.163.com/sky20081816@126/blog/static/16476102320107173226920/
http://blog.csdn.net/kevin3101/article/details/53609180
question 1: what is virtual_host
2:How does it work
一. what is it
There are four building blocks you really care about in AMQP: virtual hosts, exchanges, queues and bindings. A virtual host holds a bundle of exchanges, queues and bindings. Why would you want multiple virtual hosts? Easy. A username in RabbitMQ grants you access to a virtual host…in its entirety. So the only way to keep group A from accessing group B’s exchanges/queues/bindings/etc. is to create a virtual host for A and one for B. Every RabbitMQ server has a default virtual host named “/”. If that’s all you need, you’re ready to roll.
in its entirety:作為一個整體
紅色部分語句的意思:vhost是rabbitmq分配權限的最小細粒度。比如我們可以為一個用戶分配一個可以訪問哪個或者哪一些vhost的權限。但是不能為用戶分配一個可以訪問哪一些exchange,或者queue的權限,因為rabbitmq的權限細粒度沒有細化到交換器和隊列,他的最小細粒度是vhost(vhost中包含許多的exchanges,queues,bingdings)。所以如果exchangeA 和queueA 只能讓用戶A訪問,exchangeB 和queueB 只能讓用戶B訪問,要達到這種需求,只能為exchangeA 和queueA創建一個vhostA,為exchangeB 和queueB 創建vhostB,這樣就隔離開來了。
補充:一個broker可以開設多個vhost,用於不同用戶的權限分離
virtualHost is used as a namespace for AMQP resources (default is \"/\"), so different applications could use multiple virtual hosts on the
same AMQP server
virtual host只是起到一個命名空間的作用,所以可以多個user共同使用一個virtual host,文章開頭寫的vritual_host = '/',這個是系統默認的,就是說當我們創建一個到rabbitmq的connection時候,它的命名空間是'/',需要注意的是不同的命名空間之間的資源是不能訪問的,比如 exchang,queue ,bingding等
二.How does it work
既然vitrual host 只是一個命名空間,那么我們就可以自己創建一個嘍,怎么去干呢?這里我們需要用到工具 :rabbitmqctl,安裝rabbitMQ的時候已經安裝好了。這真是一個強大的工具阿。輸入 ./rabbitmqctl,我們可以看到

首先我們可以建立一個測試用戶(如果你想用系統默認的guest也可以)
rabbitmqctl add_user test 123456 ,這樣我們就新建了一個可以連到rabbitmq的用戶,用戶名時test,密碼是123456
我們可以用 rabbitmqctl list_users 看看有多少個用戶了,可以看到有guest和test了吧
然后 我們通過 rabbitmqctl add_vhosts命令新建一個virtual host : rabbitmqctl add_vhosts test_host
我們通過 rabbitmqctl list_vhosts命令看看現在系統有幾個vhost了。可以看到有兩個,一個是系統默認的 '/', 還有一個就 是我們新建的 test_host。
但是到這里是不夠的,我們只是聲明了一個vhost,我們還要給它分配訪問權限。
rabbitmqctl set_permissions -p test_host test "test-*" ".*" ".*",如此用戶名為test的用戶就可以訪問vitrual host為test_host的資源了,並且具備讀寫的權限。
rabbitmqctl set_permissions -p /vhost1 user_admin ".*" ".*" ".*" ,命令使用戶user_admin具有/vhost1這個virtual host中所有資源的配置、寫、讀權限以便管理其中的資源
對何種資源具有配置、寫、讀的權限通過正則表達式來匹配,具體命令如下:
set_permissions [-p <vhostpath>] <user> <conf> <write> <read>
其中,<conf> <write> <read>的位置分別用正則表達式來匹配特定的資源,如'^(amq\.gen.*|amq\.default)$'可以匹配server生成的和默認的exchange,'^$'不匹配任何資源
需要注意的是RabbitMQ會緩存每個connection或channel的權限驗證結果、因此權限發生變化后需要重連才能生效。
set_permissions [-p <vhostpath>] <user> <conf> <write> <read>
其中,<conf> <write> <read>的位置分別用正則表達式來匹配特定的資源,如'^(amq\.gen.*|amq\.default)$'可以匹配server生成的和默認的exchange,'^$'不匹配任何資源
需要注意的是RabbitMQ會緩存每個connection或channel的權限驗證結果、因此權限發生變化后需要重連才能生效。
Vhost的權限
關於rabbitmq權限的幾點:
rabbitmq的權限控制通過兩層來實現,一是vhost的權限,二是確認有權限訪問vhost后,對vhost內資源的權限控制(配置,讀,寫)
1.默認的guest用戶
安裝rabbitmq(3.3.1),並啟用management plugin后,使用默認的賬號guest登陸管理控制台,卻提示登陸失敗。
翻看官方的release文檔后,得知由於賬號guest具有所有的操作權限,並且又是默認賬號,出於安全因素的考慮,guest用戶只能通過localhost登陸使用,並建議修改guest用戶的密碼以及新建其他賬號管理使用rabbitmq(該功能是在3.3.0版本引入的)。
雖然可以以比較猥瑣的方式:將ebin目錄下rabbit.app中loopback_users里的<<"guest">>刪除,或者在配置文件rabbitmq.config中對該項進行配置,

2.權限工作流程
一個客戶端連接到服務器后,指定一個所操作虛擬機。這是權限產生作用的第一層,服務器會檢查該用戶是否有權限訪問該虛擬機,有則進行下一層,否則拒絕連接。
資源,如一個虛擬機內的交換器、隊列等,在資源上rabbitmq提供三種類型的操作,配置、讀、寫。當客戶端被允許連接到某虛擬機后,服務器根據客戶端所擁有的權限,允許其做相應的操作。
權限配置支持正則表達式,可以實現一定粒度的權限控制,比如說對某一類隊列的控制。
3.rabbitmqctl中對用戶的管理命令
rabbitmqctl list_users
add_user {username} {password}
#rabbitmqctl add_user admin 123456
delete_user {username}
#rabbitmqctl delete_user admin
change_password {username} {newpassword}
#rabbitmqctl change_password admin 111111
clear_password {username}
#rabbitmqctl clear admin
set_user_tags {username} {tag ...}
#rabbitmqctl set_user_tags admin administrator #可跟多少tag,tag為空的時候表示清除原有
set_permissions [-p vhost] {user} {conf} {write} {read}
#rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*"
clear_permissions [-p vhost] {username}
list_permissions [-p vhost]
#rabbitmqctl list_permissions -p "/"
list_user_permissions {username}
#rabbitmqctl list_user_permissions admin
我們在獲取設備連接的時候可以指定用戶,並且指定vhost,當然該用戶需要有該vhost的權限才可以。
ConnectionFactory factory =
new ConnectionFactory();
factory.setUsername(
userName);//指定用戶
factory.setPassword(
password);//用戶密碼
factory.setVirtualHost(
virtualHost); //指定vhost
factory.setHost(
hostName);//指定rabbitmq服務器的主機
factory.setPort(
portNumber);//指定rabbitmq服務器所監聽的端口號
Connection conn = factory.newConnection();
目前還有的疑問:
1.一次連接,只能指定一個vhost嗎?
2.用戶和vhost的關系,是多對多嗎?
3.如果是,那么在創建連接之后,我們的消費者能否指定的從某一個vhost的某一個queue去接收數據,或者生產者能否指定的向某一個vhost的exchange發送數據。
意思就是如果一個用戶可以擁有多個vhost的權限,是否可以創建一次連接,然后動態的切換vhost。
關於rabbitmq權限的文章
http://blog.csdn.net/zyz511919766/article/details/42292655