dubbo如何設置連接zookeeper權限
前言
最近自己的技術棧項目,再升級dubbo為2.7.5,zookeeper為3.5.6,curator-recipes升級為4.2.0的時候一直出現(xiàn)zookeeper not connected和Connection lost for ***的錯誤。
之前未升級前還是好的...隨手查看報錯源碼信息并百度,終于再stackflow上面找到原因。
設置環(huán)境參數(shù)ZKClientConfig.ENABLE_CLIENT_SASL_KEY=false,默認未true
System.setProperty(ZKClientConfig.ENABLE_CLIENT_SASL_KEY,Constant.IS_FALSE.toString());
大概意思是zookeeper作為外部應用需要向系統(tǒng)申請資源,申請資源的時候需要通過認證,而sasl是一種認證方式,添加以上那一句來繞過sasl認證。避免等待,來提高效率。
隨后繼續(xù)深進,了解到zookeeper的sasl認證相關(試了下,效果不大好,可能我姿勢不大對? 這里就不介紹zk的sasl介紹和相關配置了,有興趣的可以自行百度),并附加的深入學習了zk的ACL 權限,以及dubbo以zk未注冊中心的,權限認證!下面開始相關介紹。
zookeeper設置ACL權限
查閱dubbo的官方文檔dubbo-registry發(fā)現(xiàn)連接注冊中心的時候是可以選擇是否需要用戶名密碼,接下來就是要如何設置zookeeper的用戶名跟密碼

進入zookeeper的bin文件夾運行客戶端
./zkCli.sh
help 查看指令
[zk: localhost:2181(CONNECTED) 0] help
ZooKeeper -server host:port cmd args
stat path [watch]
set path data [version]
ls path [watch]
delquota [-n|-b] path
ls2 path [watch]
setAcl path acl
setquota -n|-b val path
history
redo cmdno
printwatches on|off
delete path [version]
sync path
listquota path
rmr path
get path [watch]
create [-s] [-e] path data acl
addauth scheme auth
quit
getAcl path
close
connect host:port如果在dubbo中沒有指定分組的話,dubbo會默認生成一個分組dubbo,也就是在zookeeper下面會有個子節(jié)點dubbo
也可以自己手動創(chuàng)建
create /dubbo
Zookeeper的ACL通過scheme:username:password:permissions來構成權限
scheme這邊主要用到2種方式,另外還有設置ip和host,這幾個沒用到的這邊就先不細說
1.auth方式(密碼明文)
添加用戶名和密碼
addauth digest admin:13871500871
授予/dubbo auth權限
setAcl /dubbo auth:admin:13871500871:rwadc
配置dubbo連接zookeeper配置文件
<dubbo:registry protocol ="zookeeper" address="127.0.0.1:2181" username="admin" password="13871500871" client="curator" />
2.digest授權方式(方式跟auth差不多)
授予/dubbo digest權限
addauth digest admin:jI+oJfxCaWyh/3Zw/r+fwhbZVRY=
setAcl /dubbo digest:admin:jI+oJfxCaWyh/3Zw/r+fwhbZVRY=:cdrwa
配置zookeeper配置文件
<dubbo:registry protocol ="zookeeper" address="127.0.0.1:2181" username="admin" password="13871500871" client="curator" />
digest 密碼生成方式:把密碼進行sha1編碼然后對結果進行base64編碼
BASE64(SHA1(password))
查看zookeeper源碼發(fā)現(xiàn),其實包里面已經(jīng)有現(xiàn)成的方法,直接調(diào)用這個類生成就行,
idPassword字符串格式:username:password
org.apache.zookeeper.server.auth.DigestAuthenticationProvider
static public String generateDigest(String idPassword) throws NoSuchAlgorithmException {
String parts[] = idPassword.split(":", 2);
byte digest[] = MessageDigest.getInstance("SHA1").digest(
idPassword.getBytes());
return parts[0] + ":" + base64Encode(digest);
}還有一個點就是要設置client="curator"
通過ZookeeperRegistry發(fā)現(xiàn)zookeeper的連接是通過zookeeperTransporter進行創(chuàng)建,
zookeeperTransporter接口分別由CuratorZookeeperTransporterZkclientZookeeperTransporter實現(xiàn),這2個分別創(chuàng)建
CuratorZookeeperClient和ZkclientZookeeperClient
public class ZkclientZookeeperTransporter implements ZookeeperTransporter {
public ZookeeperClient connect(URL url) {
return new ZkclientZookeeperClient(url);
}
}public class CuratorZookeeperTransporter implements ZookeeperTransporter {
public ZookeeperClient connect(URL url) {
return new CuratorZookeeperClient(url);
}
}查看源碼發(fā)現(xiàn)ZkclientZookeeperClient是沒有進行設置zookeeper的auth的賬號和密碼,
CuratorZookeeperClient有去獲取配置的相關用戶信息。
public ZkclientZookeeperClient(URL url) {
super(url);
client = new ZkClient(url.getBackupAddress());
client.subscribeStateChanges(new IZkStateListener() {
public void handleStateChanged(KeeperState state) throws Exception {
ZkclientZookeeperClient.this.state = state;
if (state == KeeperState.Disconnected) {
stateChanged(StateListener.DISCONNECTED);
} else if (state == KeeperState.SyncConnected) {
stateChanged(StateListener.CONNECTED);
}
}
public void handleNewSession() throws Exception {
stateChanged(StateListener.RECONNECTED);
}
});
} public CuratorZookeeperClient(URL url) {
super(url);
try {
Builder builder = CuratorFrameworkFactory.builder()
.connectString(url.getBackupAddress())
.retryPolicy(new RetryNTimes(Integer.MAX_VALUE, 1000))
.connectionTimeoutMs(5000);
String authority = url.getAuthority();
if (authority != null && authority.length() > 0) {
builder = builder.authorization("digest", authority.getBytes());
}
client = builder.build();
client.getConnectionStateListenable().addListener(new ConnectionStateListener() {
public void stateChanged(CuratorFramework client, ConnectionState state) {
if (state == ConnectionState.LOST) {
CuratorZookeeperClient.this.stateChanged(StateListener.DISCONNECTED);
} else if (state == ConnectionState.CONNECTED) {
CuratorZookeeperClient.this.stateChanged(StateListener.CONNECTED);
} else if (state == ConnectionState.RECONNECTED) {
CuratorZookeeperClient.this.stateChanged(StateListener.RECONNECTED);
}
}
});
client.start();
} catch (IOException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}cdrwa表示zookeeper的五種權限
CREATE: 創(chuàng)建子節(jié)點READ: 獲取節(jié)點數(shù)據(jù)或者當前節(jié)點的子節(jié)點列表WRITE: 節(jié)點設置數(shù)據(jù)DELETE: 刪除子節(jié)點ADMIN: 節(jié)點設置權限
如果用戶名密碼錯誤,或者沒設置,會報KeeperErrorCode = NoAuth錯誤
注:停止zookeeper,清除zookeeper文件夾下面的logs,或者用delete 刪除節(jié)點 就可以清除權限
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
關于Java整合RocketMQ實現(xiàn)生產(chǎn)消費詳解
這篇文章主要介紹了關于Java整合RocketMQ實現(xiàn)生產(chǎn)消費詳解,RocketMQ作為一款純java、分布式、隊列模型的開源消息中間件,支持事務消息、順序消息、批量消息、定時消息、消息回溯等,需要的朋友可以參考下2023-05-05
Spring+SpringMVC+Hibernate項目環(huán)境搭建的步驟(圖文)
這篇文章主要介紹了Spring+SpringMVC+Hibernate項目環(huán)境搭建的步驟(圖文),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-05-05
Springboot如何獲取配置文件application.yml中自定義的變量并使用
這篇文章主要介紹了Springboot中獲取配置文件(application.yml)中自定義的變量并使用,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-09-09
SpringBoot調(diào)用Poi-tl實現(xiàn)渲染數(shù)據(jù)并生成Word文檔
這篇文章主要為大家詳細介紹了SpringBoot如何調(diào)用Poi-tl實現(xiàn)渲染數(shù)據(jù)并生成Word文檔,文中的示例代碼講解詳細,有需要的小伙伴可以了解下2023-09-09

