ZK ACL访问的一个小demo

ZooKeeper zk=new ZooKeeper("192.168.1.188,192.168.1.189,192.168.1.190",50000,w);     

       ArrayList<ACL> acls = new ArrayList<ACL>();          

  ACL acl1=new ACL(ZooDefs.Perms.ALL, new Id("digest", DigestAuthenticationProvider.generateDigest("qingxu:taobao123")));          

  //或者把以上两行换成如下三行       

     // zk.addAuthInfo("digest","qingxu:taobao123".getBytes());       

     //ArrayList<ACL> acls = new ArrayList<ACL>();         

   //ACL acl1=new ACL(ZooDefs.Perms.ALL, new Id("auth", ""));        

    acls.add(acl1);           

 zk.create("/qingxu/child",null, acls, CreateMode.PERSISTENT);        

    Thread.sleep(50000000);            zk.close();

child这个znode对于用户qingxu来说具有所有权限它采用的digest认证方式。

其他客户端如果要访问这个znode或者创建子znode,需要首先进行认证。

<pre class="java" name="code"><span style="font-size:18px;">     ZooKeeper zk=new ZooKeeper("192.168.1.188,192.168.1.189,192.168.1.190",50000,w);
            zk.addAuthInfo<strong><span style="color:#ff0000;">("digest","qingxu:taobao123".</span></strong>getBytes());
            zk.create("/qingxu/child/sunzi2",null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            zk.close();</span>

如果这里qingxu:taobao123输入成了qingxu:taobao124,那么将会抛出NoAuthException.

 

Zk 对znode操作采用ACL进行了访问权限控制,类似于linux提供的读写权限,ZK将操作权限划分以下几种:CREATE/READ/WRITE/DELETE/ADMIN,

·        CREATE: 表示有权限创建一个子节点

·        READ: 表示可以getData或者getChildren

·        WRITE: 表示可以setData

·        DELETE: 表示可以delete子节点

·        ADMIN: 表示可以通过setACL设置znode权限

Create和delete权限是从write权限中拆分出来的,注意与linux中write的区别。ZK中使用常量类来标明了这些权限。

将这些权限与一系列Id进行关联就构成了节点的ACL控制对,可以这么看这个映射关系。

ACL=PermßàID

而ID由scheme和实际的字符串id组成。Scheme表示了与实际字符串id对应的认证scheme标识符,也就是说在对字符串id进行认证时,需要根据scheme找到对应的认证服务提供者来对id进行校验认证,例如Scheme=digest  id=qingxu:pwd,表示digest关键字对应的认证服务提供者来对qingxu:pwd进行认证,

ZK提供了目前提供了基于客户端IP(scheme=ip)和基于摘要(SHA1,scheme=digest)用户密码的两种提供者, 他们都实现了AuthenticationProvider接口, 用户也可以通过设置以zookeeper.authProvider.开头的系统属性来增加其他用户自定义的授权方式(ProviderRegistry在初始化时会将自定义的授权方式加载进来)。在ZK服务端,授权Provider以HashMap的方式驻留在内存中,key是scheme,value是AuthenticationProvider接口的实现类,这样通过AuthenticationProvider getProvider(String scheme) 就可以得到具体的认证服务了。

在客户端准备创建znode时,create方法要求指定对本znode的ACL列表,标明:谁(id)采用某种认证方式(scheme)之后可以采取某种操作(perm).

public String create(final String path,byte data[], List<ACL> acl,

           CreateMode createMode)

可以对一个znode使用多个ACL,当服务器端创建节点时会将这个ACL列表与该znode关联,并在随后某个时间持久化到snapshot中,当客户端对这个节点或者子节点进行操作时,会检查当前连接上来的客户端是否具有权限操作该节点,如果没有权限,就会抛出No Auth异常。对于有的权限认证信息,客户端不需要传递额外的信息给服务器,例如anyone,表示任何人,对于类似digest的认证服务,由于需要客户端提供用户密码,然后与服务端的用户密码进行校验(用户密码两者组合起来被认为是一个用户id),客户端输入认证服务的地方是通过通过客户端ZK的addAuthInfo(String scheme, byte auth[])方法添加对应认证信息(例如用户密码),这些认证信息会传递到服务器端做一些处理(主要是scheme服务器是否支持,对于scheme=digest主要是判定下是否super超级用户登录来了,scheme=ip就简单记录下当前登录ip),并保存在authinfo这个客户端列表中,以后这个连接就可以一直使用这个认证信息.

addAuthInfo 后的服务端流程如下:

服务器在节点进行权限检查时checkACL()流程如下:

Super用户直接通过,不进行任何权限(perm比较),可以进行任何操作。

否则,当前要进行的操作需要的权限perm与znode拥有的权限一致时,再比较用户。如果与znode上所有ACLperm都不一致,就表示没有通过校验,抛出NoAuthException异常。

如果该节点ACL是任何人都能访问(shceme=world 并且id=anyone),直接通过验证,否则,根据scheme找到认证服务provider,然后从authinfo中查找与该scheme相等同时id也match的ACL,找到则认证通过。如果所有的都没有验证通过,就抛出NoAuthException


最后:如果ZK服务器不想进行checkACL,那么服务器系统属性zookeeper.skipACL=yes即可。


 


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值