zookeeper 权限控制及watch监听机制使用

zookeeper 权限控制及watch监听机制使用,第1张

zookeeper 权限控制及watch监听机制使用

本文主要记录ZK中的相关特性,包括监听机制、权限控制等。

1. ZK特性 1.1 节点状态信息stat

节点除了存储数据内容以外,还存储了数据节点本身的一些状态信息,通过stat命令可以获得状态信息的详细内容,如下所示。

状态属性说明cZxid数据节点创建时的事务IDctime数据节点创建时的时间mZxid数据节点最后一次更新时的事务IDmtime数据节点最后一次更新时的时间pZxid数据节点的子节点列表最后一次被修改(是子节点列表变更,而不是子节点内容变更)时的事务IDcversion子节点的版本号dataVersion数据节点的版本号aclVersion数据节点的ACL版本号ephemeralOwner如果节点是临时节点,则表示创建该节点的会话的SessionID;如果节点是持久节点,则该属性值为0dataLength数据内容的长度numChildren数据节点当前的子节点个数 1.2 版本-保证分布式数据原子性

zookeeper为数据节点引入了版本的概念,每个数据节点都有三类版本信息,对数据节点任何更新 *** 作都会引起版本号的变化。

版本类型说明version当前数据节点数据内容的版本号cversion当前数据节点子节点的版本号aversion当前数据节点ACL变更版本号

版本号有点和我们经常使用的乐观锁类似。这里有两个概念说一下,一个是乐观锁,一个是悲观锁。

悲观锁:是数据库中一种非常典型且非常严格的并发控制策略。假如一个事务A正在对数据进行处理,那么在整个处理过程中,都会将数据处于锁定状态,在这期间其他事务无法对数据进行更新 *** 作。

乐观锁:乐观锁和悲观锁正好想法,它假定多个事务在处理过程中不会彼此影响,因此在事务处理过程中不需要进行加锁处理,如果多个事务对同一数据做更改,那么在更新请求提交之前,每个事务都会首先检查当前事务读取数据后,是否有其他事务对数据进行了修改。如果有修改,则回滚事务再回到zookeeper,version属性就是用来实现乐观锁机制的“写入校验“。

1.3 watcher机制

zookeeper提供了分布式数据的发布/订阅功能,zookeeper允许客户端向服务端注册一个watcher监听,当服务端的一些指定事件触发了watcher,那么服务端就会向客户端发送一个事件通知。

zookeeper提供以下几种命令来对指定节点设置监听。

get [-s] [-w] path:监听指定path节点的修改和删除事件。同样该事件也是一次性触发。

get -w /node 
# 在其他窗口执行下面命令,会触发相关事件 
set /node 123 
delete /node

ls [-s] [-w] [-R] path : 监控指定path的子节点的添加和删除事件。

ls -w /node 
# 在其他窗口执行下面命令,会触发相关事件 
create /node/node1 
delete /node/node1

注意: 当前命令设置的监听是一次性的,就是说一旦触发了一次事件监听,后续的事件都不会响应。当然我们可以通过重复订阅来解决

stat [-w] path:作用和get完全相同。

addWatch [-m mode] path

addWatch的作用是针对指定节点添加事件监听,支持两种模式

PERSISTENT,持久化订阅,针对当前节点的修改和删除事件,以及当前节点的子节点的删除和新增事件。

PERSISTENT_RECURSIVE,持久化递归订阅,在PERSISTENT的基础上,增加了子节点修改的事件触发,以及子节点的子节点的数据变化都会触发相关事件(满足递归订阅特性)

1.4 Session会话机制

如图所示,表示Zookeeper的session会话状态机制。

首先,客户端向Zookeeper Server发起连接请求,此时状态为CONNECTING

当连接建立好之后,Session状态转化为CONNECTED,此时可以进行数据的IO *** 作。

如果Client和Server的连接出现丢失,则Client又会变成CONNECTING状态

如果会话过期或者主动关闭连接时,此时连接状态为CLOSE

如果是身份验证失败,直接结束

2. ZK权限控制

Zookeeper作为一个分布式协调框架,内部存储了一些分布式系统运行时的状态的数据,比如master选举、比如分布式锁。对这些数据的 *** 作会直接影响到分布式系统的运行状态。因此,为了保证zookeeper中的数据的安全性,避免误 *** 作带来的影响。Zookeeper提供了一套ACL权限控制机制来保证数据的安全。

ACL权限控制,使用: scheme : id : perm 来标识。

Scheme(权限模式),标识授权策略

ID(授权对象)

Permission:授予的权限

ZooKeeper的权限控制是基于每个znode节点的,需要对每个节点设置权限,每个znode支持设置多种权限控制方案和多个权限,子节点不会继承父节点的权限,客户端无权访问某节点,但可能可以访问它的子节点。

2.1 Scheme权限模式

Zookeeper提供以下权限模式,所谓权限模式,就是使用什么样的方式来进行授权。

world:默认方式,相当于全部都能访问。

auth:代表已经认证通过的用户(cli中可以通过addauth digest user:pwd 来添加当前上下文中的授权用户)

digest:即用户名:密码这种方式认证,这也是业务系统中最常用的。用 username:password 字符串来产生一个MD5串,然后该串被用来作为ACL ID。认证是通过明文发送username:password 来进行的,当用在ACL时,表达式为username:base64 ,base64是password的SHA1摘要的编码。

ip:通过ip地址来做权限控制,比如 ip:192.168.1.1 表示权限控制都是针对这个ip地址的。也可以针对网段 ip:192.168.1.1/24,此时addr中的有效位与客户端addr中的有效位进行比对。

2.2 ID授权对象

指权限赋予的用户或一个指定的实体,不同的权限模式下,授权对象不同:

权限模式授权对象IP通常是一个IP地址或者IP段Digest自定义,通常是”username:base64(123456)“World只有一个ID:”anyone“Super与Digest模式一致
Id ipId1 = new Id("ip", "192.168.190.1"); 
Id ANYONE_ID_UNSAFE = new Id("world", "anyone");
2.3 Permission权限类型

指通过权限检查后可以被允许的 *** 作,create /delete /read/write/admin

Create 允许对子节点Create *** 作

Read 允许对本节点GetChildren 和GetData *** 作

Write 允许对本节点SetData *** 作

Delete 允许对子节点Delete *** 作

Admin 允许对本节点setAcl *** 作

权限模式(Schema)和授权对象主要用来确认权限验证过程中使用的验证策略: 比如ip地址、digest:username:password,匹配到验证策略并验证成功后,再根据权限 *** 作类型来决定当前客户端的访问权限。

2.4 在控制台上实现权限 *** 作

在Zookeeper中提供了ACL相关的命令如下。

getAcl getAcl  读取ACL权限 
setAcl setAcl   设置ACL权限 
addauth addauth   添加认证用户
2.4.1 World方式

我们创建一个节点后默认就是world模式。

其中, cdrwa,分别对应 create . delete. read .write . admin.

[zk: localhost:2181(CONNECTED) 14] create /world
Created /world
[zk: localhost:2181(CONNECTED) 15] getAcl /world
'world,'anyone
: cdrwa
[zk: localhost:2181(CONNECTED) 16] setAcl /world:anyone:acd
setAcl [-s] [-v version] [-R] path acl
[zk: localhost:2181(CONNECTED) 17] setAcl /world world:anyone:acd
[zk: localhost:2181(CONNECTED) 18] getAcl /world
'world,'anyone
: cda
2.4.2 IP模式

在ip模式中,首先连接到zkServer的命令需要使用如下方式:

./zkCli.sh -server 192.168.221.120:2181

接着按照IP的方式 *** 作如下:

[zk: 192.168.221.120:2181(CONNECTED) 0] create /ip-model
Created /ip-model
[zk: 192.168.221.120:2181(CONNECTED) 2] setAcl /ip-model ip:127.0.0.1:cdrwa,ip:192.168.221.120:cdrwa
[zk: 192.168.221.120:2181(CONNECTED) 3] getAcl /ip-model
'ip,'127.0.0.1
: cdrwa
'ip,'192.168.221.120
: cdrwa
2.4.3 Auth模式

auth模式的 *** 作如下:

[zk: localhost:2181(CONNECTED) 5] create /auth
Created /auth
[zk: localhost:2181(CONNECTED) 6] addauth digest cc:cc # 增加授权用户,明文用户名和密码,zk会对密码加密
[zk: localhost:2181(CONNECTED) 7] setAcl /auth auth:mic:cdrwa # 授予权限
[zk: localhost:2181(CONNECTED) 8] getAcl /auth
'digest,'cc:8/1tijQ2Mu1QuGMyP+DoAciB06I=
: cdrwa

当我们退出当前的会话后,再次连接,执行如下 *** 作,会提示没有权限.

[zk: localhost:2181(CONNECTED) 0] get /auth
Insufficient permission : /auth

这时候,我们需要重新授权:

[zk: localhost:2181(CONNECTED) 1] addauth digest cc:cc
[zk: localhost:2181(CONNECTED) 2] get /auth
null
2.4.4 Digest

使用语法,会发现使用方式和Auth模式相同。

setAcl /digest digest:用户名:密码:权限

但是有一个不一样的点,密码需要用加密后的,否则无法被识别。

密码: 用户名和密码加密后的字符串。

使用下面程序生成密码:

public static void main(String[] args) throws Exception {
   String up = "cc:cc";
   byte[] digest = MessageDigest.getInstance("SHA1").digest(up.getBytes());
   String encodeString = base64.getEncoder().encodeToString(digest);
   System.out.println(encodeString);
}

得到:8/1tijQ2Mu1QuGMyP+DoAciB06I=

再回到client上进行如下 *** 作:

[zk: localhost:2181(CONNECTED) 3] create /digest
Created /digest
[zk: localhost:2181(CONNECTED) 4] setAcl /digest digest:cc:8/1tijQ2Mu1QuGMyP+DoAciB06I=:cdrwa
[zk: localhost:2181(CONNECTED) 5] getAcl /digest
'digest,'cc:8/1tijQ2Mu1QuGMyP+DoAciB06I=
: cdrwa

当退出当前会话后,需要再次授权才能访问**/digest**节点:

[zk: localhost:2181(CONNECTED) 0] get /digest
Insufficient permission : /digest
[zk: localhost:2181(CONNECTED) 1] addauth digest cc:cc
[zk: localhost:2181(CONNECTED) 2] get /digest
null

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5708768.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存