Zookeeper 权限控制 ACL
以下是 ZooKeeper 权限控制(ACL)完整详解(中文),从 核心概念 → 权限模型 → 5 种方案 → 实际操作 → Java 代码 → 安全最佳实践,图文 + 类比 + 口诀,助你 彻底掌握 ZK 的“门禁系统”。
一、ACL 是什么?(类比:门禁卡)
| ZooKeeper ACL | 现实门禁 |
|---|---|
| 谁(Who) | 员工、访客、管理员 |
| 能做什么(What) | 读卡、开门、修改权限 |
| 哪个节点(Where) | /app/config、/locks |
| 验证方式 | 指纹、密码、IC 卡 |
ACL = Access Control List,控制 谁 能对 哪个 ZNode 进行 什么操作
二、ZooKeeper 权限模型(5 种权限位)
| 权限 | 缩写 | 含义 | 操作 |
|---|---|---|---|
| CREATE | c | 创建子节点 | create /parent/child |
| READ | r | 读取数据 + 列子节点 | get /node, ls /parent |
| WRITE | w | 修改数据 | set /node "new" |
| DELETE | d | 删除子节点 | delete /parent/child |
| ADMIN | a | 设置 ACL | setAcl /node ... |
组合示例:
crwda= 完全权限
三、身份认证方案(5 种 Scheme)
| Scheme | 说明 | 安全性 | 使用场景 |
|---|---|---|---|
world | 任何人 | 0 | 公开配置 |
ip | IP 白名单 | 1 | 内网访问 |
digest | 用户名:密码 | 3 | 生产推荐 |
sasl | Kerberos | 5 | 企业级 |
auth | 已登录用户 | 2 | 客户端认证 |
四、ACL 结构(Java 类)
ACL acl = new ACL(
Perms.READ | Perms.WRITE, // 权限位
new Id("digest", "user:hashed_password") // 身份
);
五、ACL 实战操作(zkCli.sh)
1. 默认 ACL(world:anyone:cdrwa)
create /app "data"
getAcl /app
# 'world,'anyone
# :cdrwa
2. 方案 1:world(公开读)
setAcl /config world:anyone:r
getAcl /config
# 'world,'anyone
# :r
3. 方案 2:ip(IP 白名单)
# 只允许 192.168.1.100 读写
setAcl /app ip:192.168.1.100:crwda
# 多个 IP
setAcl /app ip:192.168.1.100:crwda,ip:192.168.1.101:r
4. 方案 3:digest(用户名密码) 【生产推荐】
步骤 1:生成密码哈希
# Java 自带工具
echo -n "admin:123456" | openssl dgst -sha1 -binary | openssl base64
# 输出:rO/1oP4q7d2v3x4y5z6a7b8c9d0=
步骤 2:设置 ACL
setAcl /admin digest:admin:rO/1oP4q7d2v3x4y5z6a7b8c9d0=:cdrwa
步骤 3:客户端认证
# 登录
addauth digest admin:123456
# 现在可以操作
create /admin/secret "top secret"
get /admin/secret
未认证 →
Authentication is not valid
5. 方案 4:auth(已登录用户)
# 先登录
addauth digest user:pass123
# 设置 ACL(当前用户)
setAcl /myapp auth:user:cdrwa
# 其他客户端需登录同一用户
六、Java 代码实现(原生 + Curator)
原生 API
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.apache.zookeeper.ZooDefs.Perms;
List<ACL> acls = new ArrayList<>();
acls.add(new ACL(Perms.READ | Perms.WRITE, new Id("digest", "admin:hashed")));
zk.create("/secure", "data".getBytes(),
acls, CreateMode.PERSISTENT);
// 认证
zk.addAuthInfo("digest", "admin:123456".getBytes());
Curator 框架(推荐)
// 设置 ACL
client.create()
.withACL(ZooDefs.Ids.CREATOR_ALL_ACL) // 创建者全权
.forPath("/myapp");
// 认证
client.getAuth().add(new AuthInfo("digest", "user:pass".getBytes()));
七、ACL 继承与覆盖
| 规则 | 说明 |
|---|---|
| 子节点不继承父节点 ACL | 需显式设置 |
| 创建时可指定 | zk.create(path, data, acls, mode) |
| 批量设置 | 递归脚本 |
# 递归设置(脚本)
find_nodes() {
for node in $(ls $1); do
setAcl $1/$node world:anyone:r
find_nodes $1/$node
done
}
八、生产级 ACL 策略
| 节点路径 | 推荐 ACL | 说明 |
|---|---|---|
/config/public | world:anyone:r | 公开配置 |
/config/private | digest:admin:xxx:cdrwa | 管理员 |
/services/* | ip:10.0.0.0/8:r | 内网读 |
/locks | world:anyone:cd | 任何人可争锁 |
/admin | digest:ops:xxx:cdrwa | 运维 |
九、ACL 常见命令速查
# 查看 ACL
getAcl /path
# 设置世界读
setAcl /path world:anyone:r
# 设置 IP
setAcl /path ip:192.168.1.100:crwda
# 设置用户
setAcl /path digest:user:hashed:cdrwa
# 登录
addauth digest user:password
# 删除认证
delauth digest
十、ACL 验证测试
# 客户端 A(未认证)
get /secure/config
# → Authentication is not valid
# 客户端 B(已认证)
addauth digest admin:123456
get /secure/config
# → success
十一、安全最佳实践
| 建议 | 操作 |
|---|---|
| 关闭 world 完全权限 | 避免 cdrwa |
| 生产用 digest | 明文密码不出现在日志 |
| 最小权限原则 | r 给读,cd 给锁 |
| ACL 审计 | 定期 getAcl -R / |
| 结合网络隔离 | 防火墙 + VPC |
十二、ACL 记忆口诀
“世 IP 消 萨 认,五权创读写删管”
- 世:
world:anyone - IP:
ip:192.168.1.100 - 消:
digest:user:pass - 萨:
sasl(Kerberos) - 认:
auth(已登录) - 五权:
c r w d a
十三、ACL 权限位速记
c = create (生孩子)
r = read (看内容)
w = write (改数据)
d = delete (删孩子)
a = admin (改门禁)
十四、zkCli 完整示例
# 1. 创建节点
create /bank ""
# 2. 设置管理员权限
setAcl /bank digest:admin:rO/1oP4q7d2v3x4y5z6a7b8c9d0=:cdrwa
# 3. 尝试未认证访问
get /bank/config
# → Authentication is not valid
# 4. 认证后访问
addauth digest admin:123456
create /bank/config "balance=100"
get /bank/config
# → balance=100
十五、常见问题
| 问题 | 原因 | 解决 |
|---|---|---|
Authentication is not valid | 未认证或密码错 | addauth |
Permission denied | ACL 不匹配 | 检查 getAcl |
| 密码明文泄露 | 命令行历史 | 用 Java 客户端 |
| 子节点继承 ACL | 不继承 | 递归设置 |
总结:ACL 配置模板
# 1. 公开读
setAcl /public world:anyone:r
# 2. 内网读写
setAcl /app ip:10.0.0.0/8:crwda
# 3. 管理员
setAcl /admin digest:admin:$(echo -n "admin:123456"|openssl dgst -sha1 -binary|openssl base64):cdrwa
# 4. 登录
addauth digest admin:123456
动手练习:
- [x] 用
digest保护/secret节点 - [x] 用 Java 实现登录 + 操作
- [x] 写脚本递归设置
/config为只读 - [ ] 集成 Spring Cloud Zookeeper + ACL
需要我提供:
- ACL 自动化设置脚本(Python)
- Spring Boot + ZK ACL 集成
- ACL 审计工具
- Kerberos 认证配置
请继续提问!