前言关于zookeeper知之甚少,少之又少,只是作为dubbo的注册中心连接,某天某检测机构随手一扫然后说你们zookeeper 没有设置任何安全验证,当时就懵了,还有这种操作。zookeeper设置ACL 权限查阅dubbo的官方文档dubbo-registry发现连接注册中心的时候是可以选择是否需要用户名密码,接下来就是要如何设置zookeeper的用户名跟密码进入zookeeper的bin文件夹运行客户端./zkCli.sh-help 查看指令[zk: localhost:2181(CONNECTED) 0] -helpZooKeeper -server host:port cmd args stat path [watch] set path data [version] ls path [watch] delquota [-n|-b] path ls2 path [watch] setAcl path acl setquota -n|-b val path history redo cmdno printwatches on|off delete path [version] sync path listquota path rmr path get path [watch] create [-s] [-e] path data acl addauth scheme auth quit getAcl path close connect host:port如果在dubbo中没有指定分组的话,dubbo会默认生成一个分组dubbo,也就是在zookeeper下面会有个子节点dubbo也可以自己手动创建create /dubboZookeeper的ACL通过scheme🆔permissions来构成权限scheme这边主要用到2种方式,另外还有设置ip和host,这几个没用到的这边就先不细说1.auth方式(密码明文)添加用户名和密码addauth digest onepay:onepay授予/dubbo auth权限setAcl /dubbo auth:onepay:onepay:rwadc配置dubbo连接zookeeper配置文件<dubbo:registry protocol =“zookeeper” address=“127.0.0.1:2181” username=“onepay” password=“onepay” client=“curator” />2.digest授权方式(方式跟auth差不多)授予/dubbo digest权限setAcl /dubbo digest:onepay:T+17ezPAW0kDvN6elPD5Tdzdm00=:cdrwaaddauth digest onepay:onepay配置zookeeper配置文件<dubbo:registry protocol =“zookeeper” address=“127.0.0.1:2181” username=“onepay” password=“onepay” client=“curator” />digest 密码生成方式:把密码进行sha1编码然后对结果进行base64编码BASE64(SHA1(password))查看zookeeper源码发现,其实包里面已经有现成的方法,直接调用这个类生成就行,idPassword字符串格式: username:passwordorg.apache.zookeeper.server.auth.DigestAuthenticationProvider static public String generateDigest(String idPassword) throws NoSuchAlgorithmException { String parts[] = idPassword.split(":", 2); byte digest[] = MessageDigest.getInstance(“SHA1”).digest( idPassword.getBytes()); return parts[0] + “:” + base64Encode(digest); }还有一个点就是要设置client=“curator"通过ZookeeperRegistry发现zookeeper的连接是通过zookeeperTransporter进行创建,zookeeperTransporter接口分别由CuratorZookeeperTransporterZkclientZookeeperTransporter实现,这2个分别创建CuratorZookeeperClient和ZkclientZookeeperClientpublic class ZkclientZookeeperTransporter implements ZookeeperTransporter { public ZookeeperClient connect(URL url) { return new ZkclientZookeeperClient(url); }}public class CuratorZookeeperTransporter implements ZookeeperTransporter { public ZookeeperClient connect(URL url) { return new CuratorZookeeperClient(url); }}查看源码发现ZkclientZookeeperClient是没有进行设置zookeeper的auth的账号和密码,CuratorZookeeperClient有去获取配置的相关用户信息。 public ZkclientZookeeperClient(URL url) { super(url); client = new ZkClient(url.getBackupAddress()); client.subscribeStateChanges(new IZkStateListener() { public void handleStateChanged(KeeperState state) throws Exception { ZkclientZookeeperClient.this.state = state; if (state == KeeperState.Disconnected) { stateChanged(StateListener.DISCONNECTED); } else if (state == KeeperState.SyncConnected) { stateChanged(StateListener.CONNECTED); } } public void handleNewSession() throws Exception { stateChanged(StateListener.RECONNECTED); } }); } public CuratorZookeeperClient(URL url) { super(url); try { Builder builder = CuratorFrameworkFactory.builder() .connectString(url.getBackupAddress()) .retryPolicy(new RetryNTimes(Integer.MAX_VALUE, 1000)) .connectionTimeoutMs(5000); String authority = url.getAuthority(); if (authority != null && authority.length() > 0) { builder = builder.authorization(“digest”, authority.getBytes()); } client = builder.build(); client.getConnectionStateListenable().addListener(new ConnectionStateListener() { public void stateChanged(CuratorFramework client, ConnectionState state) { if (state == ConnectionState.LOST) { CuratorZookeeperClient.this.stateChanged(StateListener.DISCONNECTED); } else if (state == ConnectionState.CONNECTED) { CuratorZookeeperClient.this.stateChanged(StateListener.CONNECTED); } else if (state == ConnectionState.RECONNECTED) { CuratorZookeeperClient.this.stateChanged(StateListener.RECONNECTED); } } }); client.start(); } catch (IOException e) { throw new IllegalStateException(e.getMessage(), e); } }cdrwa表示zookeeper的五种权限CREATE: 创建子节点READ: 获取节点数据或者当前节点的子节点列表WRITE: 节点设置数据DELETE: 删除子节点ADMIN: 节点设置权限如果用户名密码错误,或者没设置,会报KeeperErrorCode = NoAuth错误注:停止zookeeper,清除zookeeper文件夹下面的logs,或者用delete 删除节点 就可以清除权限以上参考文档Apache Zookeeper Setting ACL