将 ACL 与 Curator 一起使用
Using ACL with Curator
使用 CuratorFramework,谁能解释一下我该怎么做:
- 创建新路径
- 为此路径设置数据
- 获取此路径
使用用户名 foo
和密码 bar
?不懂这个的user/pass就什么也做不了
我不关心为了这个问题的目的而通过明文发送的 SSL 或密码。
Apache Curator 中的 ACL 用于访问控制。因此,ZooKeeper 不提供任何身份验证机制,如 clients who don't have correct password cannot connect to ZooKeeper or cannot create ZNodes
。它可以做的是,防止 未经授权的 客户端访问特定的 Znode/ZNodes。为此,您必须设置 CuratorFramework 实例,如下所述。请记住,这将保证使用给定 ACL 创建的 ZNode 可以被同一客户端或提供相同身份验证信息的客户端再次访问。
首先,您应该按如下方式构建 CuratorFramework
实例。在这里,connectString
表示您的集合中 zookeeper 服务器的 ip and port
组合的逗号分隔列表。
CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder()
.connectString(connectString)
.retryPolicy(new ExponentialBackoffRetry(retryInitialWaitMs, maxRetryCount))
.connectionTimeoutMs(connectionTimeoutMs)
.sessionTimeoutMs(sessionTimeoutMs);
/*
* If authorization information is available, those will be added to the client. NOTE: These auth info are
* for access control, therefore no authentication will happen when the client is being started. These
* info will only be required whenever a client is accessing an already create ZNode. For another client of
* another node to make use of a ZNode created by this node, it should also provide the same auth info.
*/
if (zkUsername != null && zkPassword != null) {
String authenticationString = zkUsername + ":" + zkPassword;
builder.authorization("digest", authenticationString.getBytes())
.aclProvider(new ACLProvider() {
@Override
public List<ACL> getDefaultAcl() {
return ZooDefs.Ids.CREATOR_ALL_ACL;
}
@Override
public List<ACL> getAclForPath(String path) {
return ZooDefs.Ids.CREATOR_ALL_ACL;
}
});
}
CuratorFramework client = builder.build();
现在你必须开始了。
client.start();
正在创建路径。
client.create().withMode(CreateMode.PERSISTENT).forPath("/your/ZNode/path");
这里,CreateMode
指定了你想要创建的节点类型。可用类型有 PERSISTENT,EPHEMERAL,EPHEMERAL_SEQUENTIAL,PERSISTENT_SEQUENTIAL,CONTAINER
。 Java Docs
如果您不确定到/your/ZNode
的路径是否已经存在,您也可以创建它们。
client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/your/ZNode/path");
设置数据
您可以在创建ZNode时设置数据,也可以稍后设置。如果您在创建时设置数据,请将数据作为 byte
数组作为第二个参数传递给 forPath()
方法。
client.create().withMode(CreateMode.PERSISTENT).forPath("/your/ZNode/path","your data as String".getBytes());
如果以后再做,(数据应该以字节数组的形式给出)
client.setData().forPath("/your/ZNode/path",data);
终于
我不明白你所说的 get this path
是什么意思。 Apache Curator
是一个 java 客户端(比 Curator Recipes 的客户端多),它在后台使用 Apache Zookeeper
并隐藏了 Zookeeper 的边缘情况和复杂性。在Zookeeper中,他们使用ZNodes
的概念来存储数据。您可以将其视为 Linux 目录结构。所有 ZNodePaths
都应该以 /
(root) 开头,您可以根据需要继续指定目录,如 ZNodePaths。例如:/someName/another/test/sample
.
如上图所示,ZNode以树状结构组织。每个 ZNode
最多可以存储 1MB 的数据。因此,如果要检索存储在 ZNode 中的数据,则需要知道到该 ZNode 的路径。 (就像您应该知道数据库的 table 和列以便检索数据一样)。
如果要检索给定路径中的数据,
client.getData().forPath("/path/to/ZNode");
当您想使用 Curator 时,您需要知道的就是这些。
还有一件事
Apache Curator 中的 ACL 用于访问控制。也就是说,如果你设置ACLProvider
如下,
new ACLProvider() {
@Override
public List<ACL> getDefaultAcl () {
return ZooDefs.Ids.CREATOR_ALL_ACL;
}
@Override
public List<ACL> getAclForPath (String path){
return ZooDefs.Ids.CREATOR_ALL_ACL;
}
}
只有具有与创建者相同凭据的客户端才会被授予访问相应 ZNode 的权限。授权细节设置如下(参见客户端构建示例)。还有其他可用的 ACL 模式,例如 OPEN_ACL_UNSAFE
如果将其设置为 ACLProvider,则不会进行任何访问控制。
authorization("digest", authorizationString.getBytes())
稍后将使用它们来控制对给定 ZNode 的访问。
总之,如果你想防止别人干扰你的ZNodes,可以将ACLProvider设置为return CREATOR_ALL_ACL
,将授权设置为digest
,如上图。只有使用相同授权字符串 ("username:password"
) 的 CuratorFramework 实例才能访问这些 ZNode。但它不会阻止其他人在不干扰你的路径中创建 ZNode。
希望你找到了你想要的:-)
这不是原始问题的一部分,但我想我会分享我想出的解决方案,其中使用的凭据决定访问级别。
我没能找到任何示例,一直停留在这个页面上,所以也许它会对其他人有所帮助。我仔细研究了 Curator Framework 的源代码,幸运的是 org.apache.curator.framework.recipes.leader.TestLeaderAcls class 在那里为我指明了正确的方向。
所以在这个例子中:
- 一个通用客户端跨多个应用程序使用,只需要从 ZK 读取数据。
- 另一个管理客户端可以读取、删除和更新 ZK 中的节点。
- 只读或管理员访问权限由使用的凭据决定。
完全控制的管理员客户端
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.ACLProvider;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.apache.zookeeper.server.auth.DigestAuthenticationProvider;
public class AdminClient {
protected static CuratorFramework client = null;
public void initializeClient() throws NoSuchAlgorithmException {
String zkConnectString = "127.0.0.1:2181";
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
final List<ACL> acls = new ArrayList<>();
//full-control ACL
String zkUsername = "adminuser";
String zkPassword = "adminpass";
String fullControlAuth = zkUsername + ":" + zkPassword;
String fullControlDigest = DigestAuthenticationProvider.generateDigest(fullControlAuth);
ACL fullControlAcl = new ACL(ZooDefs.Perms.ALL, new Id("digest", fullControlDigest));
acls.add(fullControlAcl);
//read-only ACL
String zkReadOnlyUsername = "readuser";
String zkReadOnlyPassword = "readpass";
String readOnlyAuth = zkReadOnlyUsername + ":" + zkReadOnlyPassword;
String readOnlyDigest = DigestAuthenticationProvider.generateDigest(readOnlyAuth);
ACL readOnlyAcl = new ACL(ZooDefs.Perms.READ, new Id("digest", readOnlyDigest));
acls.add(readOnlyAcl);
//create the client with full-control access
client = CuratorFrameworkFactory.builder()
.connectString(zkConnectString)
.retryPolicy(retryPolicy)
.authorization("digest", fullControlAuth.getBytes())
.aclProvider(new ACLProvider() {
@Override
public List<ACL> getDefaultAcl() {
return acls;
}
@Override
public List<ACL> getAclForPath(String string) {
return acls;
}
})
.build();
client.start();
//Now create, read, delete ZK nodes
}
}
只读客户端
import java.security.NoSuchAlgorithmException;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
public class ReadOnlyClient {
protected static CuratorFramework client = null;
public void initializeClient() throws NoSuchAlgorithmException {
String zkConnectString = "127.0.0.1:2181";
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
String zkReadOnlyUsername = "readuser";
String zkReadOnlyPassword = "readpass";
String readOnlyAuth = zkReadOnlyUsername + ":" + zkReadOnlyPassword;
client = CuratorFrameworkFactory.builder()
.connectString(zkConnectString)
.retryPolicy(retryPolicy)
.authorization("digest", readOnlyAuth.getBytes())
.build();
client.start();
//Now read ZK nodes
}
}
使用 CuratorFramework,谁能解释一下我该怎么做:
- 创建新路径
- 为此路径设置数据
- 获取此路径
使用用户名 foo
和密码 bar
?不懂这个的user/pass就什么也做不了
我不关心为了这个问题的目的而通过明文发送的 SSL 或密码。
Apache Curator 中的 ACL 用于访问控制。因此,ZooKeeper 不提供任何身份验证机制,如 clients who don't have correct password cannot connect to ZooKeeper or cannot create ZNodes
。它可以做的是,防止 未经授权的 客户端访问特定的 Znode/ZNodes。为此,您必须设置 CuratorFramework 实例,如下所述。请记住,这将保证使用给定 ACL 创建的 ZNode 可以被同一客户端或提供相同身份验证信息的客户端再次访问。
首先,您应该按如下方式构建 CuratorFramework
实例。在这里,connectString
表示您的集合中 zookeeper 服务器的 ip and port
组合的逗号分隔列表。
CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder()
.connectString(connectString)
.retryPolicy(new ExponentialBackoffRetry(retryInitialWaitMs, maxRetryCount))
.connectionTimeoutMs(connectionTimeoutMs)
.sessionTimeoutMs(sessionTimeoutMs);
/*
* If authorization information is available, those will be added to the client. NOTE: These auth info are
* for access control, therefore no authentication will happen when the client is being started. These
* info will only be required whenever a client is accessing an already create ZNode. For another client of
* another node to make use of a ZNode created by this node, it should also provide the same auth info.
*/
if (zkUsername != null && zkPassword != null) {
String authenticationString = zkUsername + ":" + zkPassword;
builder.authorization("digest", authenticationString.getBytes())
.aclProvider(new ACLProvider() {
@Override
public List<ACL> getDefaultAcl() {
return ZooDefs.Ids.CREATOR_ALL_ACL;
}
@Override
public List<ACL> getAclForPath(String path) {
return ZooDefs.Ids.CREATOR_ALL_ACL;
}
});
}
CuratorFramework client = builder.build();
现在你必须开始了。
client.start();
正在创建路径。
client.create().withMode(CreateMode.PERSISTENT).forPath("/your/ZNode/path");
这里,CreateMode
指定了你想要创建的节点类型。可用类型有 PERSISTENT,EPHEMERAL,EPHEMERAL_SEQUENTIAL,PERSISTENT_SEQUENTIAL,CONTAINER
。 Java Docs
如果您不确定到/your/ZNode
的路径是否已经存在,您也可以创建它们。
client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/your/ZNode/path");
设置数据
您可以在创建ZNode时设置数据,也可以稍后设置。如果您在创建时设置数据,请将数据作为 byte
数组作为第二个参数传递给 forPath()
方法。
client.create().withMode(CreateMode.PERSISTENT).forPath("/your/ZNode/path","your data as String".getBytes());
如果以后再做,(数据应该以字节数组的形式给出)
client.setData().forPath("/your/ZNode/path",data);
终于
我不明白你所说的 get this path
是什么意思。 Apache Curator
是一个 java 客户端(比 Curator Recipes 的客户端多),它在后台使用 Apache Zookeeper
并隐藏了 Zookeeper 的边缘情况和复杂性。在Zookeeper中,他们使用ZNodes
的概念来存储数据。您可以将其视为 Linux 目录结构。所有 ZNodePaths
都应该以 /
(root) 开头,您可以根据需要继续指定目录,如 ZNodePaths。例如:/someName/another/test/sample
.
如上图所示,ZNode以树状结构组织。每个 ZNode
最多可以存储 1MB 的数据。因此,如果要检索存储在 ZNode 中的数据,则需要知道到该 ZNode 的路径。 (就像您应该知道数据库的 table 和列以便检索数据一样)。
如果要检索给定路径中的数据,
client.getData().forPath("/path/to/ZNode");
当您想使用 Curator 时,您需要知道的就是这些。
还有一件事
Apache Curator 中的 ACL 用于访问控制。也就是说,如果你设置ACLProvider
如下,
new ACLProvider() {
@Override
public List<ACL> getDefaultAcl () {
return ZooDefs.Ids.CREATOR_ALL_ACL;
}
@Override
public List<ACL> getAclForPath (String path){
return ZooDefs.Ids.CREATOR_ALL_ACL;
}
}
只有具有与创建者相同凭据的客户端才会被授予访问相应 ZNode 的权限。授权细节设置如下(参见客户端构建示例)。还有其他可用的 ACL 模式,例如 OPEN_ACL_UNSAFE
如果将其设置为 ACLProvider,则不会进行任何访问控制。
authorization("digest", authorizationString.getBytes())
稍后将使用它们来控制对给定 ZNode 的访问。
总之,如果你想防止别人干扰你的ZNodes,可以将ACLProvider设置为return CREATOR_ALL_ACL
,将授权设置为digest
,如上图。只有使用相同授权字符串 ("username:password"
) 的 CuratorFramework 实例才能访问这些 ZNode。但它不会阻止其他人在不干扰你的路径中创建 ZNode。
希望你找到了你想要的:-)
这不是原始问题的一部分,但我想我会分享我想出的解决方案,其中使用的凭据决定访问级别。
我没能找到任何示例,一直停留在这个页面上,所以也许它会对其他人有所帮助。我仔细研究了 Curator Framework 的源代码,幸运的是 org.apache.curator.framework.recipes.leader.TestLeaderAcls class 在那里为我指明了正确的方向。
所以在这个例子中:
- 一个通用客户端跨多个应用程序使用,只需要从 ZK 读取数据。
- 另一个管理客户端可以读取、删除和更新 ZK 中的节点。
- 只读或管理员访问权限由使用的凭据决定。
完全控制的管理员客户端
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.ACLProvider;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.apache.zookeeper.server.auth.DigestAuthenticationProvider;
public class AdminClient {
protected static CuratorFramework client = null;
public void initializeClient() throws NoSuchAlgorithmException {
String zkConnectString = "127.0.0.1:2181";
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
final List<ACL> acls = new ArrayList<>();
//full-control ACL
String zkUsername = "adminuser";
String zkPassword = "adminpass";
String fullControlAuth = zkUsername + ":" + zkPassword;
String fullControlDigest = DigestAuthenticationProvider.generateDigest(fullControlAuth);
ACL fullControlAcl = new ACL(ZooDefs.Perms.ALL, new Id("digest", fullControlDigest));
acls.add(fullControlAcl);
//read-only ACL
String zkReadOnlyUsername = "readuser";
String zkReadOnlyPassword = "readpass";
String readOnlyAuth = zkReadOnlyUsername + ":" + zkReadOnlyPassword;
String readOnlyDigest = DigestAuthenticationProvider.generateDigest(readOnlyAuth);
ACL readOnlyAcl = new ACL(ZooDefs.Perms.READ, new Id("digest", readOnlyDigest));
acls.add(readOnlyAcl);
//create the client with full-control access
client = CuratorFrameworkFactory.builder()
.connectString(zkConnectString)
.retryPolicy(retryPolicy)
.authorization("digest", fullControlAuth.getBytes())
.aclProvider(new ACLProvider() {
@Override
public List<ACL> getDefaultAcl() {
return acls;
}
@Override
public List<ACL> getAclForPath(String string) {
return acls;
}
})
.build();
client.start();
//Now create, read, delete ZK nodes
}
}
只读客户端
import java.security.NoSuchAlgorithmException;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
public class ReadOnlyClient {
protected static CuratorFramework client = null;
public void initializeClient() throws NoSuchAlgorithmException {
String zkConnectString = "127.0.0.1:2181";
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
String zkReadOnlyUsername = "readuser";
String zkReadOnlyPassword = "readpass";
String readOnlyAuth = zkReadOnlyUsername + ":" + zkReadOnlyPassword;
client = CuratorFrameworkFactory.builder()
.connectString(zkConnectString)
.retryPolicy(retryPolicy)
.authorization("digest", readOnlyAuth.getBytes())
.build();
client.start();
//Now read ZK nodes
}
}