1. Overview
1.概述
In this tutorial, we’re going to create a CLI application to test connections to any LDAP Authentication server. We won’t use LDAP to secure our application, since this can be done better using Spring Security LDAP, for example.
在本教程中,我们将创建一个CLI应用程序来测试与任何LDAP 认证服务器的连接。我们不会使用 LDAP 来保护我们的应用程序,因为使用Spring Security LDAP,例如,可以更好地完成这一工作。
Having a tool to quickly check the validity of LDAP connections is useful even before developing applications that use them. It’s also useful when developing some kind of integration between applications, especially in the setup phase. And we’ll do it using core Java classes. So no additional dependencies are required.
拥有一个快速检查LDAP连接有效性的工具甚至在开发使用它们的应用程序之前就已经很有用了。在开发应用程序之间的某种集成时,它也很有用,特别是在设置阶段。而且 我们将使用核心的Java类来做这件事。所以不需要额外的依赖性。
2. LDAP Java Client
2.LDAP Java客户端
Let’s start by creating our only class, LdapConnectionTool. We’ll start with the main method. To keep things simple, all our logic will go here:
让我们开始创建我们唯一的类,LdapConnectionTool。我们将从main方法开始。为了保持简单,我们所有的逻辑都在这里。
public class LdapConnectionTool {
public static void main(String[] args) {
// ...
}
}
First, we’ll pass our parameters as system properties. We’ll be using default values for the factory (LdapCtxFactory) and authType (simple) variables. LdapCtxFactory is the core Java class responsible for the whole process of connecting to a server and populating user attributes. And a simple authentication type means our password will be sent as clear text. Similarly, we’ll default our query variable to the user, so we can specify either one or both. We’ll see usage details later on:
首先,我们将把我们的参数作为系统属性传递。我们将使用factory(LdapCtxFactory)和authType(simple)变量的默认值。LdapCtxFactory是核心Java类,负责连接到服务器和填充用户属性的整个过程。而一个simple认证类型意味着我们的密码将以明文形式发送。同样,我们将默认我们的query变量为user,所以我们可以指定一个或两个。我们将在后面看到使用细节。
String factory = System.getProperty("factory", "com.sun.jndi.ldap.LdapCtxFactory");
String authType = System.getProperty("authType", "simple");
String url = System.getProperty("url");
String user = System.getProperty("user");
String password = System.getProperty("password");
String query = System.getProperty("query", user);
Next, we’re going to create our environment map, which holds all properties necessary for a connection using InitialDirContext:
接下来,我们要创建我们的环境图,它拥有使用InitialDirContext进行连接所需的所有属性。
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, factory);
env.put(Context.SECURITY_AUTHENTICATION, authType);
env.put(Context.PROVIDER_URL, url);
We don’t want to require a user and password because some servers allow anonymous access:
我们不希望要求用户和密码,因为有些服务器允许匿名访问。
if (user != null) {
env.put(Context.SECURITY_PRINCIPAL, user);
env.put(Context.SECURITY_CREDENTIALS, password);
}
When testing connections, it’s common that we pass in an incorrect URL or that the server is simply unresponsive. Since the default client behavior blocks indefinitely until a response is received, we’ll define timeout parameters. The wait time is defined in milliseconds:
在测试连接时,我们通常会传入一个不正确的URL,或者服务器根本没有反应。由于默认的客户端行为会无限期地阻塞,直到收到响应为止,我们将定义超时参数。等待时间的单位是毫秒。
env.put("com.sun.jndi.ldap.read.timeout", "5000");
env.put("com.sun.jndi.ldap.connect.timeout", "5000");
After that, we try to establish a connection with a new instance of InitialDirContext, along with basic exception handling. This is essential since we’ll use it to diagnose common problems. Likewise, since we’re developing a CLI application, we print our messages to the standard output:
之后,我们尝试与一个新的InitialDirContext实例建立连接,同时进行基本的异常处理。这是必不可少的,因为我们将用它来诊断常见的问题。同样地,由于我们正在开发一个CLI应用程序,我们将信息打印到标准输出。
DirContext context = null;
try {
context = new InitialDirContext(env);
System.out.println("success");
// ...
} catch (NamingException e) {
System.out.println(e.getMessage());
} finally {
context.close();
}
Finally, we use our context variable to query for all attributes resulting from our optional query:
最后,我们使用我们的context变量来查询由我们的可选query产生的所有属性。
if (query != null) {
Attributes attributes = context.getAttributes(query);
NamingEnumeration<? extends Attribute> all = attributes.getAll();
while (all.hasMoreElements()) {
Attribute next = all.next();
String key = next.getID();
Object value = next.get();
System.out.println(key + "=" + value);
}
}
3. Common Mistakes
3.常见错误
In this section, we’ll go over some common mistakes and error messages encountered when trying to connect to a server:
在本节中,我们将讨论一些常见的错误和试图连接到服务器时遇到的错误信息。
- Wrong Base DN: We’ll get “error code 49 – Invalid Credentials” if we don’t set the Base DN properly. Since every server has its own structure, we should always check this first, as this message can be misleading.
- No anonymous connections: We’ll get the error “ERR_229 Cannot authenticate user” if we don’t configure our server to allow anonymous access.
4. Usage
4.使用情况
Now that we’re all set up, we can use our application. Firstly, let’s build it as a jar, rename it to ldap-connection-tool.jar, then try one of the following examples. Note that these values are completely dependent on our server configuration.
现在我们都设置好了,我们可以使用我们的应用程序。首先,让我们将其构建为一个jar,将其重命名为ldap-connection-tool.jar,然后尝试以下例子之一。注意,这些值完全取决于我们的服务器配置。
Connecting with a user and password:
用一个用户和密码连接。
java -cp ldap-connection-tool.jar \
-Durl=ldap://localhost:389 \
-Duser=uid=gauss,dc=baeldung,dc=com \
-Dpassword=password \
com.baeldung.jndi.ldap.connectionTool.LdapConnectionTool
Specifying only the server URL for a quick connection test:
只指定服务器URL进行快速连接测试。
java -cp ldap-connection-tool.jar \
-Durl=ldap://localhost:389 \
com.baeldung.jndi.ldap.connectionTool.LdapConnectionTool
Also, specifying a query along with a user and password, we can connect with a specific user but query for another. This is useful if we need to connect as an administrator, for example, before performing a query. Similarly, if we connect with a user with enough privileges, we can see protected attributes, such as passwords.
另外,指定一个query以及user和password,我们可以用一个特定的用户来连接,但查询另一个用户。如果我们需要以管理员身份连接,例如在执行查询之前,这很有用。类似地,如果我们用一个有足够权限的用户连接,我们可以看到受保护的属性,如密码。
Finally, passing system properties as input is fine when dealing with simple parameters. But, there are more elegant ways of developing CLI applications, like Spring Shell. We should use something like that for anything more complex.
最后,在处理简单的参数时,将系统属性作为输入传递是可以的。但是,在开发CLI应用程序方面有更优雅的方法,比如Spring Shell。我们应该使用类似的方法来处理更复杂的事情。
5. Conclusion
5.总结
In this article, we created a CLI application that can connect to an LDAP server and run connection tests. Also, there are more application usage examples in the unit tests. And as always, the source code is available over on GitHub.
在这篇文章中,我们创建了一个CLI应用程序,可以连接到LDAP服务器并运行连接测试。此外,在单元测试中还有更多的应用程序使用示例。而且像往常一样,源代码可以在GitHub上找到,。