如何使用 Apache 目录服务器和客户端实现身份验证 Java API

How to implement authentication with Apache Directory Server and Client Java API

我正在尝试构建一个应用程序,其中的用户和组将在 Apache 目录服务器及其客户端中进行管理 API。

这是应用程序启动时针对服务器执行的 ldif 文件的示例:

dn: o=koosserydesk 对象类:可扩展对象 对象类别:顶部 对象类:域 dc: koosserydesk o: koosserydesk<br> dn: ou=desks,o=koosserydesk 对象类:组织单位 对象类:顶部 ou: 书桌<br> dn: ou=users,o=koosserydesk 对象类:组织单位 对象类:顶部 你:用户<br> dn: cn=John Milton,ou=users,o=koosserydesk 对象类:organizationalPerson 对象类:人 对象类:inetOrgPerson 对象类:顶部 cn: 约翰·弥尔顿 SN: 杰米尔顿 uid:jmilton 用户密码:: e1NIQTUxMn1lQThmcUQzOVgva2xxSm1jOGlZK2JoWitUVFhzWElFRmZHeWJ1b

我想让 John Milton 在输入相应的 uid/userPassword 时被识别为 我的应用 的已验证用户。类似于:

布尔认证(字符串 uid){<br> //我应该使用 connection.bind("uid="+uid, userPassword);??<br> return 某事; }
请注意,John Milton 针对 ApacheDS 进行身份验证(用于对条目进行操作)对我来说并不是最重要的。我只是想让 ApacheDs 充当我的用户的数据库,即 获取我的用户的 uid,检查密码,如果匹配 return true,或者 return false .
可能这不是我应该尝试处理的方式,但我对 Ldap 协议和周围的东西还很陌生,所以不要怀疑我的问题是否有点奇怪!
等待提议!

这可能不是重复的,但以下问题的第二个答案(由 Nikolay Antipov 提供)可能会回答您的问题: How to check user password in ldap whith java with given LdapContext?


这是一种解决方案,可用于使用 DN 以外的其他内容对用户进行身份验证,例如 uidsAMAccountName

要做的步骤是:

  1. 连接到 LDAP 服务器
  2. 向我们知道其 DN 和凭据的服务用户进行身份验证
  3. 搜索你想要认证的用户,用一些属性搜索他(例如sAMAccountName
  4. 获取我们找到的用户的 DN
  5. 使用找到的 DN 和密码打开另一个到 LDAP 服务器的连接
  6. 如果找到用户并且身份验证有效,那么您就没问题

代码示例:

public static boolean performAuthentication() {

    // service user
    String serviceUserDN = "cn=Mister Service,ou=Users,dc=example,dc=com";
    String serviceUserPassword = "abc123#!$";

    // user to authenticate
    String identifyingAttribute = "uid";
    String identifier = "maxdev";
    String password = "jkl987.,-";
    String base = "ou=Users,dc=example,dc=com";

    // LDAP connection info
    String ldap = "localhost";
    int port = 10389;
    String ldapUrl = "ldap://" + ldap + ":" + port;

    // first create the service context
    DirContext serviceCtx = null;
    try {
        // use the service user to authenticate
        Properties serviceEnv = new Properties();
        serviceEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        serviceEnv.put(Context.PROVIDER_URL, ldapUrl);
        serviceEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
        serviceEnv.put(Context.SECURITY_PRINCIPAL, serviceUserDN);
        serviceEnv.put(Context.SECURITY_CREDENTIALS, serviceUserPassword);
        serviceCtx = new InitialDirContext(serviceEnv);

        // we don't need all attributes, just let it get the identifying one
        String[] attributeFilter = { identifyingAttribute };
        SearchControls sc = new SearchControls();
        sc.setReturningAttributes(attributeFilter);
        sc.setSearchScope(SearchControls.SUBTREE_SCOPE);

        // use a search filter to find only the user we want to authenticate
        String searchFilter = "(" + identifyingAttribute + "=" + identifier + ")";
        NamingEnumeration<SearchResult> results = serviceCtx.search(base, searchFilter, sc);

        if (results.hasMore()) {
            // get the users DN (distinguishedName) from the result
            SearchResult result = results.next();
            String distinguishedName = result.getNameInNamespace();

            // attempt another authentication, now with the user
            Properties authEnv = new Properties();
            authEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
            authEnv.put(Context.PROVIDER_URL, ldapUrl);
            authEnv.put(Context.SECURITY_PRINCIPAL, distinguishedName);
            authEnv.put(Context.SECURITY_CREDENTIALS, password);
            new InitialDirContext(authEnv);

            System.out.println("Authentication successful");
            return true;
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (serviceCtx != null) {
            try {
                serviceCtx.close();
            } catch (NamingException e) {
                e.printStackTrace();
            }
        }
    }
    System.err.println("Authentication failed");
    return false;
}