首页 > 数据库技术 > 详细

ZooKeeper 笔记(5) ACL(Access Control List)访问控制列表

时间:2015-09-28 16:04:40      阅读:609      评论:0      收藏:0      [点我收藏+]

zk做为分布式架构中的重要中间件,通常会在上面以节点的方式存储一些关键信息,默认情况下,所有应用都可以读写任何节点,在复杂的应用中,这不太安全,ZK通过ACL机制来解决访问权限问题,详见官网文档:http://zookeeper.apache.org/doc/r3.4.6/zookeeperProgrammers.html#sc_ZooKeeperAccessControl

总体来说,ZK的节点有5种操作权限

CREATE、READ、WRITE、DELETE、ADMIN 也就是 增、删、改、查、管理权限,这5种权限简写为crwda(即:每个单词的首字符缩写)

 

身份的认证有4种方式

world:默认方式,相当于全世界都能访问
auth:代表已经认证通过的用户(当前app对应的已经登录OS用户?)
digest:即用户名:密码这种方式认证,这也是业务系统中最常用的
ip:使用Ip地址认证

 

Cli命令行下可以这样测试:

技术分享

通过getAcl命令可以发现,刚创建的节点,默认是 world,anyone的认证方式,具有cdrwa所有权限

 

继续捣鼓:

技术分享

先给/test,增加了增加了user1:12345的只读(r)权限控制,然后get /test时,提示认证无效,说明访问控制起作用了,但是不能理解的是,delete /test 却成功了。

 

代码使用:

zookeeper有一个很好用的客户端开源项目zkclient,官网地址为:http://github.com/zkclient ,其最新片0.7-dev已经支持ACL了,使用方法:

git clone https://github.com/sgroschupf/zkclient (把代码拉到本地)

修改

build.gradle 找到92行

uploadArchives {

    repositories.mavenDeployer {
        //repository(url: "file:///tmp/mavenRepo")
        repository(url: "http://172.21.129.56:8081/nexus/content/repositories/thirdparty/") {
            authentication(userName: admin, password: admin123)
        }
        beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
        pom.project {
            name ‘ZkClient‘
            packaging ‘jar‘
            description ‘A zookeeper client, that makes life a little easier.‘
            url ‘https://github.com/sgroschupf/zkclient‘
            licenses {
                license {
                    name ‘The Apache Software License, Version 2.0‘
                    url ‘http://www.apache.org/licenses/LICENSE-2.0.txt‘
                    distribution ‘repo‘
                }
            }
            scm {
                url ‘https://github.com/sgroschupf/zkclient‘
                connection ‘scm:git:git://github.com/sgroschupf/zkclient.git‘
                developerConnection ‘scm:git:https://github.com/sgroschupf/zkclient.git‘
            }
            developers {
                developer {
                    id ‘sgroschupf‘
                    name ‘Stefan Groshupf‘
                }
                developer {
                    id ‘pvoss‘
                    name ‘Peter Voss‘
                }
                developer {
                    id ‘jzillmann‘
                    name ‘Johannes Zillmann‘
                }
            }
        }
    }
}

把这一段干掉,否则编译时会出错

然后(windows环境,把./gradew 换成gradlew)

./gradlew test (测试)

./gradlew jars (编译生成jar包)

./gradlew install (安装到本机maven仓库)  

 

新建一个maven项目,pom.xml参考下面设置:

技术分享
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <modelVersion>4.0.0</modelVersion>
 6 
 7     <groupId>yjmyzz</groupId>
 8     <artifactId>zkclient-demo</artifactId>
 9     <version>1.0</version>
10 
11     <dependencies>
12         <dependency>
13             <groupId>org.apache.zookeeper</groupId>
14             <artifactId>zookeeper</artifactId>
15             <version>3.4.6</version>
16         </dependency>
17 
18         <dependency>
19             <groupId>com.101te</groupId>
20             <artifactId>zkclient</artifactId>
21             <version>0.7</version>
22             <classifier>dev</classifier>
23         </dependency>
24 
25         <dependency>
26             <groupId>log4j</groupId>
27             <artifactId>log4j</artifactId>
28             <version>1.2.17</version>
29         </dependency>
30 
31     </dependencies>
32 
33 
34 </project>
View Code

 

然后写一段代码测试一下:

package yjmyzz.zk;

import org.I0Itec.zkclient.ZkClient;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.apache.zookeeper.data.Stat;
import org.apache.zookeeper.server.auth.DigestAuthenticationProvider;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


public class Main {

    private static final String zkAddress = "localhost:2181";
    private static final String testNode = "/test";
    private static final String readAuth = "read-user:123456";
    private static final String writeAuth = "write-user:123456";
    private static final String deleteAuth = "delete-user:123456";
    private static final String allAuth = "super-user:123456";
    private static final String adminAuth = "admin-user:123456";
    private static final String digest = "digest";

    private static void initNode() throws NoSuchAlgorithmException {
        ZkClient zkClient = new ZkClient(zkAddress);
        zkClient.addAuthInfo(digest, allAuth.getBytes());

        if (zkClient.exists(testNode)) {
            zkClient.delete(testNode);
            System.out.println("节点删除成功!");
        }

        List<ACL> acls = new ArrayList<ACL>();
        acls.add(new ACL(ZooDefs.Perms.ALL, new Id(digest, DigestAuthenticationProvider.generateDigest(allAuth))));
        acls.add(new ACL(ZooDefs.Perms.READ, new Id(digest, DigestAuthenticationProvider.generateDigest(readAuth))));
        acls.add(new ACL(ZooDefs.Perms.WRITE, new Id(digest, DigestAuthenticationProvider.generateDigest(writeAuth))));
        acls.add(new ACL(ZooDefs.Perms.DELETE, new Id(digest, DigestAuthenticationProvider.generateDigest(deleteAuth))));
        acls.add(new ACL(ZooDefs.Perms.ADMIN, new Id(digest, DigestAuthenticationProvider.generateDigest(adminAuth))));
        zkClient.createPersistent(testNode, "test-data", acls);

        System.out.println(zkClient.readData(testNode));
        System.out.println("节点创建成功!");
        zkClient.close();
    }

    private static void readTest() {
        ZkClient zkClient = new ZkClient(zkAddress);

        try {
            System.out.println(zkClient.readData(testNode));//没有认证信息,读取会出错
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }

        try {
            zkClient.addAuthInfo(digest, adminAuth.getBytes());
            System.out.println(zkClient.readData(testNode));//admin权限与read权限不匹配,读取也会出错
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }

        try {
            zkClient.addAuthInfo(digest, readAuth.getBytes());
            System.out.println(zkClient.readData(testNode));//只有read权限的认证信息,才能正常读取
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }

        zkClient.close();
    }

    private static void writeTest() {
        ZkClient zkClient = new ZkClient(zkAddress);

        try {
            zkClient.writeData(testNode, "new-data");//没有认证信息,写入会失败
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }

        try {
            zkClient.addAuthInfo(digest, writeAuth.getBytes());
            zkClient.writeData(testNode, "new-data");//加入认证信息后,写入正常
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }

        try {
            zkClient.addAuthInfo(digest, readAuth.getBytes());
            System.out.println(zkClient.readData(testNode));//读取新值验证
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }

        zkClient.close();
    }

    private static void deleteTest() {
        ZkClient zkClient = new ZkClient(zkAddress);
        //zkClient.addAuthInfo(digest, deleteAuth.getBytes());
        try {
            //System.out.println(zkClient.readData(testNode));
            zkClient.delete(testNode);
            System.out.println("节点删除成功!");
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
        zkClient.close();
    }

//    private static void deleteTest2() throws IOException, InterruptedException, KeeperException {
//        //使用zookeeper原生的API进行删除(测试结果:ACL好象也不起作用,不加任何ACL信息也能删除)
//        ZooKeeper zk = new ZooKeeper(zkAddress, 300000, new DemoWatcher());
//        zk.delete(testNode, -1);
//        System.out.println("节点删除成功");
//        zk.close();
//    }
//
//    static class DemoWatcher implements Watcher {
//        @Override
//        public void process(WatchedEvent event) {
//            System.out.println("----------->");
//            System.out.println("path:" + event.getPath());
//            System.out.println("type:" + event.getType());
//            System.out.println("stat:" + event.getState());
//            System.out.println("<-----------");
//        }
//    }

    private static void changeACLTest() {
        ZkClient zkClient = new ZkClient(zkAddress);
        //注:zkClient.setAcl方法查看源码可以发现,调用了readData、setAcl二个方法
        //所以要修改节点的ACL属性,必须同时具备read、admin二种权限
        zkClient.addAuthInfo(digest, adminAuth.getBytes());
        zkClient.addAuthInfo(digest, readAuth.getBytes());
        try {
            List<ACL> acls = new ArrayList<ACL>();
            acls.add(new ACL(ZooDefs.Perms.ALL, new Id(digest, DigestAuthenticationProvider.generateDigest(adminAuth))));
            zkClient.setAcl(testNode, acls);
            Map.Entry<List<ACL>, Stat> aclResult = zkClient.getAcl(testNode);
            System.out.println(aclResult.getKey());
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
        zkClient.close();
    }


    public static void main(String[] args) throws Exception {

        initNode();

        System.out.println("---------------------");

        readTest();

        System.out.println("---------------------");

        writeTest();

        System.out.println("---------------------");

        changeACLTest();

        System.out.println("---------------------");

        deleteTest();

        //deleteTest2();

    }
}

 

输出结果:

test-data
节点创建成功!
---------------------
org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /test
org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /test
test-data
---------------------
org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /test
new-data
---------------------
[31,s{‘digest,‘admin-user:mAlW21Phn07yOvWnKJYq2sCMoZw=}
]
---------------------
节点删除成功!

从zkclient的使用结果看,对于delete,仍然不能理解的是,根本不用设置任何AuthInfo,也一样能删除成功,不明学厉,希望知道的朋友解惑,不胜感激。  

 

ZooKeeper 笔记(5) ACL(Access Control List)访问控制列表

原文:http://www.cnblogs.com/yjmyzz/p/zookeeper-acl-demo.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!