ZooKeeper是支持权限管理的,能够控制对节点的访问权限,不管是使用ZooKeeper原生APi还是使用ZkClient API,亦或是使用Curator API,我们在创建节点的时候都可以为节点授权,代码如下所示:
/原生APi创建节点,授予的权限为ZooDefs.Ids.OPEN_ACL_UNSAFE
//后续我们会讲述这个权限
zooKeeper.create("/zktest2","zktest".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
//ZkClient为我们提供的API中有的默认使用Ids.OPEN_ACL_UNSAFE,有的则需要传入//权限比如下面的代码,我们需要传入一个权限集合
public String create(final String path, Object data, final List<ACL> acl, final CreateMode mode){
.....
}
//而在Curator中则是使用fluent风格的方法传入的权限列表,代码如下
framework.create()
.withACL(new ArrayList<ACL>()) //传入权限列表,如果不传使用默认
.creatingParentsIfNeeded()
.withMode(CreateMode.PERSISTENT)
.forPath("/createNode1/node1/n1");
使用权限可以控制客户端有权利访问哪些节点,我们在创建客户端的时候可以为客户端添加权限,代码如下:
ZkClient zk = ZkClientUtil.getZkClient();
//可添加多个权限 模式 用户 密码
zk.addAuthInfo("digest","user:password".getBytes());
ZooKeeper zk = ZooKeeperUtil.getZookeeper();
//可以添加多个权限
zk.addAuthInfo("digest","user:password".getBytes());
//Curator则使用fluent风格添加授权,同样可以添加多个
CuratorFrameworkFactory.builder()
.authorization("digest","user:passowrd".getBytes())
上面我们通过代码讲述了给节点授权和给客户端授权,可以使得客户端只能访问可以有权限的节点,而没有权限的节点则无法访问。下面我们讲述ZooKeeper的权限到底是什么。学过Shiro的人很轻易理解,某人有某些角色可以做什么事情,同样ZooKeeper也是类似,该权限在ZooKeeper中的ZooDefs类中的内部接口Perms中被定义代码如下所示:
public interface Perms {
int READ = 1; //读权限
int WRITE = 2; //写权限
int CREATE = 4; //创建权限
int DELETE = 8; //删除权限
int ADMIN = 16; //管理权限
int ALL = 31; //以上所有权限
}
知道有哪些权限之后就可以定义这些权限由哪些用户拥有,在ZooKeeper中有Id实例表示一个用户,它用以一个schema字段和id字段,代码如下所示:
public class Id implements Record {
private String scheme;
private String id;
public Id() {
}
......
}
上面的Id实例表示一个用户,id标识唯一标识,而Schema则表示采用哪种方案进行权限管理,ZooKeeper支持一下几种方式的权限管理:
- world: 它下面只有一个id, 叫anyone, world:anyone代表任何人,zookeeper中对所有人有权限的结点就是属于world:anyone的
- auth: 它不需要id, 只要是通过authentication的user都有权限(zookeeper支持通过kerberos来进行authencation, 也支持username/password形式的authentication)
- digest: 它对应的id为username:BASE64(SHA1(password)),它需要先通过username:password形式的authentication
- ip: 它对应的id为客户机的IP地址,设置的时候可以设置一个ip段,比如ip:192.168.1.0/16, 表示匹配前16个bit的IP段
- super: 在这种scheme情况下,对应的id拥有超级权限,可以做任何事情(cdrwa)
看完上面的权限管理模式之后,最终将授权封装为ACL实例,如下为ZooKeeper客户端为我们提供的默认的授权,它也是ZooDefs中的一个内部接口Ids:
public interface Ids {
//world模式管理权限,id为anyone
Id ANYONE_ID_UNSAFE = new Id("world", "anyone");
//auth模式管理权限,不需要id,置为””
Id AUTH_IDS = new Id("auth", "");
//拥有所有权限
ArrayList<ACL> OPEN_ACL_UNSAFE = new ArrayList(Collections.singletonList(new ACL(31, ANYONE_ID_UNSAFE)));
//auth模式授权管理
ArrayList<ACL> CREATOR_ALL_ACL = new ArrayList(Collections.singletonList(new ACL(31, AUTH_IDS)));
//读权限
ArrayList<ACL> READ_ACL_UNSAFE = new ArrayList(Collections.singletonList(new ACL(1, ANYONE_ID_UNSAFE)));
}
除此之外,我们也可以提供自己的权限管理,比如前面提到的degist模式。这里不在用代码展示,有兴趣的可以自己通过代码学习。