使用Java API操作zookeeper的acl許可權

at_1發表於2021-09-09

預設匿名許可權

ZooKeeper提供瞭如下幾種驗證模式(scheme):

  • digest:Client端由使用者名稱和密碼驗證,譬如user:password,digest的密碼生成方式是Sha1摘要的base64形式

  • auth:不使用任何id,代表任何已確認使用者。

  • ip:Client端由IP地址驗證,譬如172.2.0.0/24

  • world:固定使用者為anyone,為所有Client端開放許可權

  • super:在這種scheme情況下,對應的id擁有超級許可權,可以做任何事情(cdrwa)

注意的是,exists操作和getAcl操作並不受ACL許可控制,因此任何客戶端可以查詢節點的狀態和節點的ACL。

節點的許可權(perms)主要有以下幾種:

  • Create 允許對子節點Create操作

  • Read 允許對本節點GetChildren和GetData操作

  • Write 允許對本節點SetData操作

  • Delete 允許對子節點Delete操作

  • Admin 允許對本節點setAcl操作

Znode ACL許可權用一個int型的十進位制數字perms表示,perms的5個二進位制位分別表示setacl、delete、create、write、read。比如0x1f=adcwr,0x1=----r,0x15=a-c-r。

以下示例在建立節點的時候,賦予該節點的許可權為預設匿名許可權,許可權位為adcwr,換成十進位制數字表示就是3
1,十六進位制則是0x1f。程式碼如下:

package org.zero01.zk.demo;import org.apache.zookeeper.*;import org.apache.zookeeper.data.ACL;import org.apache.zookeeper.data.Stat;import java.util.List;/** * @program: zookeeper-connection * @description: zookeeper 操作節點acl許可權演示 * @author: 01 * @create: 2018-04-27 09:20 **/public class ZKNodeAcl implements Watcher {    // 叢集模式則是多個ip    private static final String zkServerIps = "192.168.190.128:2181,192.168.190.129:2181,192.168.190.130:2181";    // 超時時間    private static final Integer timeout = 5000;    private static ZooKeeper zooKeeper;    private static Stat stat;    // Watch事件通知方法    public void process(WatchedEvent watchedEvent) {    }    public static void main(String[] args) throws Exception {        zooKeeper = new ZooKeeper(zkServerIps, timeout, new ZKNodeAcl());        // 這樣建立的節點是預設匿名許可權的:ZooDefs.Ids.OPEN_ACL_UNSAFE        String result = zooKeeper.create("/testAclNode", "test data".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);        Thread.sleep(1000);        // 獲取該節點的acl許可權資訊        List<ACL> aclList = zooKeeper.getACL("/testAclNode", stat);        for (ACL acl : aclList) {            System.out.println("許可權scheme id:" + acl.getId());            // 獲取的是十進位制的int型數字            System.out.println("許可權位:" + acl.getPerms());        }        // 避免與服務端的連線馬上斷開        Thread.sleep(1000);    }}

控制檯輸出內容如下:

許可權scheme id:'world,'anyone許可權位:31

ZooDefs.Ids可以直接使用的許可權如下:

ZooDefs.Ids.OPEN_ACL_UNSAFE   // 預設匿名許可權,許可權scheme id:'world,'anyone,許可權位:31(adcwr)ZooDefs.Ids.READ_ACL_UNSAFE  // 只讀許可權,許可權scheme id:'world,'anyone,許可權位:1(r)

自定義使用者許可權

本節介紹如何自定義使用者許可權,這裡使用digest進行演示,因為平時工作中digest是用得最多的。我們都知道digest是使用密文進行設定的,所以我們需要自定義一個工具類來加密明文密碼得到密文密碼。程式碼如下:

package org.zero01.zk.util;import org.apache.zookeeper.server.auth.DigestAuthenticationProvider;public class AclUtils {    public static String getDigestUserPwd(String id) throws Exception {        // 加密明文密碼        return DigestAuthenticationProvider.generateDigest(id);    }}

然後修改 ZKNodeAcl 類的程式碼如下:

package org.zero01.zk.demo;import org.apache.zookeeper.*;import org.apache.zookeeper.data.ACL;import org.apache.zookeeper.data.Id;import org.apache.zookeeper.data.Stat;import org.zero01.zk.util.AclUtils;import java.util.ArrayList;import java.util.List;/** * @program: zookeeper-connection * @description: zookeeper 操作節點acl許可權演示 * @author: 01 * @create: 2018-04-27 09:20 **/public class ZKNodeAcl implements Watcher {    // 叢集模式則是多個ip    private static final String zkServerIps = "192.168.190.128:2181,192.168.190.129:2181,192.168.190.130:2181";    // 超時時間    private static final Integer timeout = 5000;    private static ZooKeeper zooKeeper;    private static Stat stat;    public void process(WatchedEvent watchedEvent) {    }    public static void main(String[] args) throws Exception {        zooKeeper = new ZooKeeper(zkServerIps, timeout, new ZKNodeAcl());        // 自定義使用者認證訪問        List<ACL> acls = new ArrayList<ACL>();  // 許可權列表        // 第一個引數是許可權scheme,第二個引數是加密後的使用者名稱和密碼        Id user1 = new Id("digest", AclUtils.getDigestUserPwd("user1:123456a"));        Id user2 = new Id("digest", AclUtils.getDigestUserPwd("user2:123456b"));        acls.add(new ACL(ZooDefs.Perms.ALL, user1));  // 給予所有許可權        acls.add(new ACL(ZooDefs.Perms.READ, user2));  // 只給予讀許可權        acls.add(new ACL(ZooDefs.Perms.DELETE | ZooDefs.Perms.CREATE, user2));  // 多個許可權的給予方式,使用 | 位運算子        // 使用自定義的許可權列表去建立節點        String result = zooKeeper.create("/testDigestNode", "test data".getBytes(), acls, CreateMode.PERSISTENT);        if (result != null) {            System.out.println("建立節點:t" + result + "t成功...");        }        Thread.sleep(1000);        // 獲取該節點的acl許可權資訊        List<ACL> aclList = zooKeeper.getACL("/testDigestNode", stat);        for (ACL acl : aclList) {            System.out.println("n-----------------------n");            System.out.println("許可權scheme id:" + acl.getId());            System.out.println("許可權位:" + acl.getPerms());        }        Thread.sleep(1000);    }}

控制檯輸出資訊如下:

建立節點:   /testDigestNode 成功...-----------------------許可權scheme id:'digest,'user1:TQYTqd46qVVbWpOd02tLO5qb+JM=許可權位:31-----------------------許可權scheme id:'digest,'user2:CV4ED0rE6SxA3h/DN/WyScDMbCs=許可權位:1-----------------------許可權scheme id:'digest,'user2:CV4ED0rE6SxA3h/DN/WyScDMbCs=許可權位:12

我們可以到伺服器上檢視該節點的ACL資訊是否一致:

[zk: localhost:2181(CONNECTED) 15] getAcl /testDigestNode'digest,'user1:TQYTqd46qVVbWpOd02tLO5qb+JM=: cdrwa'digest,'user2:CV4ED0rE6SxA3h/DN/WyScDMbCs=: r'digest,'user2:CV4ED0rE6SxA3h/DN/WyScDMbCs=: cd[zk: localhost:2181(CONNECTED) 16]

如果我們需要操作一個設定了digest許可權的節點,那麼就需要登入用於相應許可權的使用者才行。在程式碼上也是如此,我們需要先透過addAuthInfo新增使用者資訊(賬戶:明文密碼)才能夠操作其擁有許可權的節點。以下示例演示如何使用addAuthInfo新增使用者資訊並操作相應的節點,修改main方法的程式碼如下:

...public class ZKNodeAcl implements Watcher {    ...    public static void main(String[] args) throws Exception {        zooKeeper = new ZooKeeper(zkServerIps, timeout, new ZKNodeAcl());        // 註冊過的使用者必須透過addAuthInfo才能操作節點,參考命令列 addauth        zooKeeper.addAuthInfo("digest", "user1:123456a".getBytes());        String result = zooKeeper.create("/testDigestNode/testOneNode", "test data".getBytes(), ZooDefs.Ids.CREATOR_ALL_ACL, CreateMode.PERSISTENT);        if (result != null) {            System.out.println("建立子節點:t" + result + "t成功...");        }        // 獲取節點資料        byte[] data = zooKeeper.getData("/testDigestNode/testOneNode", false, stat);        System.out.println(new String(data));        // 設定節點資料        zooKeeper.setData("/testDigestNode/testOneNode", "new test data".getBytes(), 0);        Thread.sleep(1000);    }}

控制檯輸出資訊如下:

建立子節點:  /testDigestNode/testOneNode 成功...test data

ip許可權

以上我們簡單演示了預設匿名許可權以及自定義的digest許可權,下面簡單演示下自定義ip許可權的設定方式。修改 ZKNodeAcl 類中的main方法程式碼如下:

...public class ZKNodeAcl implements Watcher {    ...    public static void main(String[] args) throws Exception {        zooKeeper = new ZooKeeper(zkServerIps, timeout, new ZKNodeAcl());        // ip方式的acl        List<ACL> aclsIP = new ArrayList<ACL>();  // 許可權列表        // 第一個引數是許可權scheme,第二個引數是ip地址        Id ipId1 = new Id("ip", "192.168.190.1");        aclsIP.add(new ACL(ZooDefs.Perms.ALL, ipId1));  // 給予所有許可權        // 使用自定義的許可權列表去建立節點        String result = zooKeeper.create("/testIpNode", "this is test ip node data".getBytes(), aclsIP, CreateMode.PERSISTENT);        if (result != null) {            System.out.println("建立節點:t" + result + "t成功...");        }        Thread.sleep(1000);        // 獲取該節點的acl許可權資訊        List<ACL> aclList = zooKeeper.getACL(result, stat);        for (ACL acl : aclList) {            System.out.println("n-----------------------n");            System.out.println("許可權scheme id:" + acl.getId());            System.out.println("許可權位:" + acl.getPerms());        }        Thread.sleep(1000);        // 獲取節點資料,驗證ip是否有許可權        byte[] data = zooKeeper.getData("/testIpNode", false, stat);        System.out.println("n-----------------------n");        System.out.println(result + " 節點當前的資料為:" + new String(data));    }}

控制檯輸出資訊如下:

建立節點:   /testIpNode 成功...-----------------------許可權scheme id:'ip,'192.168.190.1許可權位:31-----------------------/testIpNode 節點當前的資料為:this is test ip node data

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1817/viewspace-2815342/,如需轉載,請註明出處,否則將追究法律責任。

相關文章