package com.ggj.java.zclient; import lombok.extern.slf4j.Slf4j; import org.I0Itec.zkclient.ZkClient; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.ZooDefs; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.data.ACL; import org.apache.zookeeper.data.Id; import org.apache.zookeeper.server.auth.DigestAuthenticationProvider; import java.io.IOException; import java.util.*; /** * @author:gaoguangjin * @Description:生成环境创建的zookeeper节点需要带有安全验证 * @Email:[email protected] * @Date 2016/4/20 13:38 */ @Slf4j public class SafeZclient { public static void main(String[] args) throws IOException { server(); client(); //查看zookeeper节点 // ls(); } private static void ls() { for (int i = 0; i <20 ; i++) { ZkClient zc = new ZkClient("127.0.0.1:2181"); if(!zc.exists("/tt")) zc.create("/tt", "test", CreateMode.EPHEMERAL); log.info(zc.readData("/tt")); } } private static void client() { try { ZkClient zc = new ZkClient("localhost:2181"); String userTwo = "gao:gao"; zc.addAuthInfo("digest", userTwo.getBytes()); //使用admin就可以创建 // String userOne = "admin:admin"; // zc.addAuthInfo("digest",userOne.getBytes()); String data = zc.readData("/safe"); log.info("只读用户 " + userTwo + "读取safe节点返回数据:" + data); zc.create("/safe2", "test", CreateMode.EPHEMERAL); log.info("只读用户创建节点safe2成功:" + zc.readData("/safe2")); zc.create("/safe/test", "zookeeper加密是针对节点加密的", CreateMode.EPHEMERAL); log.info("只读用户创建节点失败:" + zc.readData("/safe/test")); } catch (Exception e) { e.printStackTrace(); } } /** * server端对safe接点加密 */ private static void server() { try { ZkClient zc = new ZkClient("localhost:2181"); List<ACL> acls = getACL(zc); if (zc.exists("/safe")) zc.delete("/safe"); zc.create("/safe", "safe", acls, CreateMode.PERSISTENT); } catch (Exception e) { e.printStackTrace(); } } /** * 授权访问 * Zookeeper对权限的控制是节点级别的,而且不继承,即对父节点设置权限,其子节点不继承父节点的权限 * Zookeeper提供了几种认证方式 * world:有个单一的ID,anyone,表示任何人。 * auth:不使用任何ID,表示任何通过验证的用户(是通过ZK验证的用户?连接到此ZK服务器的用户?)。 * digest:使用 用户名:密码 字符串生成MD5哈希值作为ACL标识符ID。权限的验证通过直接发送用户名密码字符串的方式完成, * ip:使用客户端主机ip地址作为一个ACL标识符,ACL表达式是以 addr/bits 这种格式表示的。ZK服务器会将addr的前bits位与客户端地址的前bits位来进行匹配验证权限。 * @param zooKeeper */ private static List<ACL> getACL(ZkClient zooKeeper) throws Exception { // 配置两个用户admin有读写权限,gao有读的权限 String userOne = "admin:admin"; String userTwo = "gao:gao"; // zooKeeper.addAuthInfo("digest",userOne.getBytes("UTF-8")); Id idOne = new Id("digest", DigestAuthenticationProvider.generateDigest(userOne)); Id idTwo = new Id("digest", DigestAuthenticationProvider.generateDigest(userTwo)); // 读 ACL acl = new ACL(ZooDefs.Perms.ALL, idOne); // 写 ACL aclRead = new ACL(ZooDefs.Perms.READ, idTwo); List<ACL> acls = Arrays.asList(acl, aclRead); return acls; } }