3

《zookeeper介绍及环境搭建》《zookeeper客户端的使用》《zookeeper java api介绍》三篇文章中,分别介绍了ZooKeeper的实验环境搭建ZooKeeper的数据结构ZooKeeper客户端的使用ZooKeeper提供的Java API。本篇文章我们将详细讨论ZooKeeper的另一个重要概念——ZooKeeper的节点权限。

ZooKeeper节点权限基本概念

ZooKeeper节点的数据结构非常类似于Linux文件系统的结构。在Linux文件系统中,每个文件或目录针对不同的用户和用户组都具有相应的rwx权限。同样的,在ZooKeeper中,每个节点针对不同的用户或主机也具有相应的权限。下面我们来看下ZooKeeper中节点权限的基本概念。

  1. 权限模式schema
    在ZooKeeper中,权限模式schema有两种类型,分别是ip和digest。
    ip模式是基于ip白名单的方式指定某个服务器具有哪些权限。
    digest模式是基于用户名和密码的方式指定哪个人具有什么样的权限。
  2. 授权对象ID
    在ip权限模式下,ID就是具体的ip地址字符串。
    在digest权限模式下,ID是username:Base64(Sha1(username:password))字符串。
  3. 权限permission
    在ZooKeeper中,有create(c)、delete(d)、read(r)、write(w)和admin(a)这五种权限类型。

在ZooKeeper中,就是通过schema、ID和permission指定一个节点的权限信息。

权限对象ACL

在ZooKeeper中,权限的信息是通过org.apache.zookeeper.data.ACL这个类指定的。ACL类的部分源码如下:

public class ACL implements Record {
    private int perms;
    private Id id;
    . . .
}

org.apache.zookeeper.data.Id类的部分源码如下:

public class Id implements Record {
    private String scheme;
    private String id;
    . . .
}    

在ACL类中,perms字段对应的就是我们上面提到的权限(permission)字段。而在Id类中的scheme和id两个字段对应的就是权限模式(schema)和授权对象(ID)。
我们通过下面的代码,就可以构造一个针对ip的权限对象:

ACL aclIp = new ACL(ZooDefs.Perms.READ | ZooDefs.Perms.WRITE, new Id("ip","192.168.1.110"));

ACL构造函数中的第一个参数是permission信息,可以通过ZooDefs.Perms.READ | ZooDefs.Perms.WRITE这种方式同时指定多个权限。ACL构造函数的第二个参数是一个Id对象,Id对象中包含了schema和授权对象的信息,这里指定schema采用ip白名单的方式,授权对象是对应的服务器ip地址。
下面的代码可以采用schema为digest的方式构造一个ACL对象:

String authStr = DigestAuthenticationProvider.generateDigest("poype:123456");
ACL aclDigest = new ACL(ZooDefs.Perms.READ | ZooDefs.Perms.WRITE, new Id("digest",authStr));

这里构造的Id对象采用digest模式构造,authStr是包含用户名和密码信息的字符串。当schema为digest时,授权对象是username:Base64(Sha1(username:password))形式的字符串。为了简化我们编程,ZooKeeper提供了对应的工具类,我们可以通过DigestAuthenticationProvider.generateDigest这个方法生成对应的授权对象字符串。这里poype是用户名,123456是密码。
下面的代码使用构造好的两个ACL对象创建一个zk节点:

ArrayList<ACL> acls = new ArrayList<ACL>();
acls.add(aclIp);
acls.add(aclDigest);
// 创建节点时用acls作为权限信息
String path = zooKeeper.create("/poype", "789".getBytes(), acls, CreateMode.PERSISTENT);

上面构造的/poype节点同时具有aclIp和aclDigest两个对象指定的权限。也就是说,/poype节点可以被ip地址为192.168.1.110的服务器读写,也可以被用户名为poype,密码是123456的用户读写。
此时在一台没有权限的机器上访问/poype节点,就会抛出下面的异常:
没有权限异常

为了使该服务器可以访问/poype节点,可以使用用户名和密码给为该服务器增加授权。
图片描述

使用命令addauth digest poype:123456增加digest授权。
可以通过下面的代码增加digest授权:

zooKeeper.addAuthInfo("digest","poype:123456".getBytes());

poype
428 声望79 粉丝