ZooKeeper ACL

ZooKeeper通过ACL来对ZNode进行访问控制。ZooKeeper客户端为ZNode指定ACL列表,ZooKeeper服务器根据ACL列表判定某个请求ZNode的客户端是否有对应操作的权限。

一个ACL对象由Permissions和Ids两部分组成。

Permissions用一组权限位(permission bits)来表示对应的权限,0表示无权限,1表示有权限。ZooKeeper中有5种权限,从低位到高位分别是READ、WRITE、CREATE、DELETE和ADMIN,它们的含义是:

* READ: 允许获取该节点的值和列出子节点。
* WRITE: 允许设置该节点的值。
* CREATE: 允许创建子节点。
* DELETE: 可以删除子节点。
* ADMIN: 允许为该节点设置权限。

ACL的Permissions可以是以上5种权限中的1种或多种,例如org.apache.zookeeper.ZooDefs.Perms定义的ALL类型,就是将以上5种权限做个‘或’运算,表示拥有所有权限。

1
2
3
4
5
6
7
8
public interface Perms {
    int READ = 1 << 0;
    int WRITE = 1 << 1;
    int CREATE = 1 << 2;
    int DELETE = 1 << 3;
    int ADMIN = 1 << 4;
    int ALL = READ | WRITE | CREATE | DELETE | ADMIN;
}

ZooKeeper中,ZNode没有Owner的概念,那些拥有ADMIN权限的客户端即等价于Owner,通过改变ZNode的ACL来进行权限管理。

如果说Permissions定义了ZNode有哪些操作可以做,那么Ids定义了ZNode有哪些人可以做。Ids由两部分组成:schema和expression,共同标识了一个允许接入的ZooKeeper客户端。schema用于区分客户端的类型,expression表示该类型下客户端的标识。ZooKeeper有内置的schema,用户也可以自定义。内置的schema有:

* world: world schema下只有一个expression: anyone。表示任何人。
* auth: auth schema下的expression为空。表示任何已经通过认证的客户端。
* digest: digest schema下的expression格式为username:password,相当于为ZNode指定一个“用户名+密码”,其他客户端要行使相应权限时,需要事先验证“用户名+密码”。服务器端为ZNode存储的认证信息为username:base64(SHA1(password))。
* ip: ip schema下的expression为CIDR格式的ip地址。

以下是一个利用digest schema验证的Demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 初始化两类权限。admin拥有所有权限。guest只有写权限。
List<ACL> acls = new ArrayList<ACL>();
Id id1 = new Id("digest", 
        DigestAuthenticationProvider.generateDigest("admin:admin"));
ACL acl1 = new ACL(ZooDefs.Perms.ALL, id1);
Id id2 = new Id("digest", 
        DigestAuthenticationProvider.generateDigest("guest:guest"));
ACL acl2 = new ACL(ZooDefs.Perms.WRITE, id2);
acls.add(acl1);
acls.add(acl2);
 
// zk1用guest认证,创建/test ZNode。
// /test允许admin任意操作,允许guest只能进行写操作。
ZooKeeper zk1 = new ZooKeeper("127.0.0.1:2181", 2000, null);
zk1.addAuthInfo("digest", "guest:guest".getBytes());
zk1.create("/test", "data".getBytes(), acls, CreateMode.PERSISTENT);
 
// zk1尝试读取/test
// ZNode节点值,抛org.apache.zookeeper.KeeperException$NoAuthException异常。
try {
    System.out.println("zk1: " + new String(zk1.getData("/test", false, null)));
} catch (Exception e) {
    e.printStackTrace();
}
 
// zk2用admin登陆,可以正常读取/test ZNode节点值。
ZooKeeper zk2 = new ZooKeeper("127.0.0.1:2181", 2000, null);
zk2.addAuthInfo("digest", "admin:admin".getBytes());
try {
    System.out.println("zk2: " + new String(zk2.getData("/test", false, null)));
} catch (Exception e) {
    e.printStackTrace();
}
 
zk1.close();
zk2.close();

你可能感兴趣的:(ZooKeeper ACL)