ACL的使用
ACL权限设置可分为三部分:权限模式(Scheme)、授权对象(ID)、权限信息(Permission),最终组成一条“scheme:id:permission”格式的 ACL 请求信息。
权限模式:Scheme
设置 ZooKeeper 服务器进行权限验证的方式。可分为两种类型,一种是范围验证,另外一种是口令验证。
范围验证:ZooKeeper 可以针对一个 IP 或者一段 IP 地址授予某种权限。 口令验证:也可以理解为用户名密码的方式,Digest 认证,ZooKeeper 服务端会对密码 部分使用 SHA-1 和 BASE64 算法进行加密。
权限模式 Super,客户端可以对 ZooKeeper 上的任意数据节点进行任意操作。
world 模式:设置了 world 权限模式系统中的所有用户操作都可以不进行权限验证。
授权对象(ID)
授权对象就是说我们要把权限赋予谁 选择采用 IP 方式,使用的授权对象可以是一个 IP 地址或 IP 地址段; 使用 Digest 或 Super 方式,则对应于一个用户名。 World 模式,授权对象是授权系统中所有的用户。
权限信息(Permission)
权限就是指我们可以在数据节点上执行的操作种类,一共有以下五种:
每个节点都有维护自身的 ACL 权限数据,即使是该节点的子节点也是有自己的 ACL 权限而不是直接继承其父节点的权限。
可插拔的授权机制
实现方式
- 实现AuthenticationProvider接口
- 将自定义的权限控制注册到 ZooKeeper 服务器中。常见方式有两种:通过设置系统属性来注册和在配置文件中zoo.cfg中进行配置。
ACL内部实现原理
后面我们简单看一下Zookeeper是如何实现ACL的。
客户端处理过程
- 客户端通过ClientCnxn向服务端发送ACL权限信息变更请求,将scheme和auth封装成AuthPacket类。
- 用RequestHeader方法表示是权限操作请求,最后封装到Packet中,并添加到outgoingQueue队列。发送给服务端
服务端处理过程
服务端将客户端ACL请求存储在服务器上
- 调用 readRequest()的processPacket方法处理节点授权请求
- processPacket内部,反序列化客户端请求,并封装到AuthPacket对象中。
- getServerProvider判断不同的实现类。
- 调用其 handleAuthentication()进行权限认证
服务端如何进行权限认证
- 通过 PrepRequestProcessor 中的 checkAcl 函数检查对应的请求权限
- 如果该节点有权限设置则循环遍历节点信息进行检查
总体来说,客户端在 ACL 权限请求发送过程的步骤比较简单:首先是封装该请求的类型,之后将权限信息封装到 request 中并发送给服务端。而服务器的实现比较复杂,首先分析请求类型是否是权限相关操作,之后根据不同的权限模式(scheme)调用不同的实现类验证权限最后存储权限信息。本课时的例子采用了授权接口 addAuth 而没有采用权限设置接口 setAcl,是因为权限设置接口相对简单,其核心功能点已经包括在授权接口实现中。而在授权接口中,值得注意的是会话的授权信息存储在 ZooKeeper 服务端的内存中,如果客户端会话关闭,授权信息会被删除。下次连接服务器后,需要重新调用授权接口进行授权。