java - 使用 Java 的 LDAP 身份验证

标签 java authentication ldap

我需要为应用程序进行 LDAP 身份验证。

我尝试了以下程序:

import java.util.Hashtable;  

import javax.naming.Context;  
import javax.naming.NamingException;  
import javax.naming.ldap.InitialLdapContext;  
import javax.naming.ldap.LdapContext;  


public class LdapContextCreation {  
    public static void main(String[] args) {  
        LdapContextCreation ldapContxCrtn = new LdapContextCreation();  
        LdapContext ctx = ldapContxCrtn.getLdapContext();  
    }  
    public LdapContext getLdapContext(){  
        LdapContext ctx = null;  
        try{  
            Hashtable env = new Hashtable();  
            env.put(Context.INITIAL_CONTEXT_FACTORY,  "com.sun.jndi.ldap.LdapCtxFactory");  
            env.put(Context.SECURITY_AUTHENTICATION, "Simple");  
            //it can be <domain\\userid> something that you use for windows login  
            //it can also be  
            env.put(Context.SECURITY_PRINCIPAL, "username@domain.com");  
            env.put(Context.SECURITY_CREDENTIALS, "password");  
            //in following property we specify ldap protocol and connection url.  
            //generally the port is 389  
            env.put(Context.PROVIDER_URL, "ldap://server.domain.com");  
            ctx = new InitialLdapContext(env, null);  
            System.out.println("Connection Successful.");  
        }catch(NamingException nex){  
            System.out.println("LDAP Connection: FAILED");  
            nex.printStackTrace();  
        }  
        return ctx;  
    }  

}

得到以下异常:

LDAP Connection: FAILED
javax.naming.AuthenticationException: [LDAP: error code 49 - Invalid Credentials]
    at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3053)
    at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2999)
    at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2801)
    at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2715)
    at com.sun.jndi.ldap.LdapCtx.(LdapCtx.java:305)
    at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:187)
    at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:205)
    at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:148)
    at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:78)
    at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:235)
    at javax.naming.InitialContext.initializeDefaultInitCtx(InitialContext.java:318)
    at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:348)
    at javax.naming.InitialContext.internalInit(InitialContext.java:286)
    at javax.naming.InitialContext.init(InitialContext.java:308)
    at javax.naming.ldap.InitialLdapContext.(InitialLdapContext.java:99)
    at LdapContextCreation.getLdapContext(LdapContextCreation.java:27)
    at LdapContextCreation.main(LdapContextCreation.java:12)

Few more points to consider:

  1. Earlier I was using tomcat 5.3.5 but somebody told me that only tomcat 6 supports it so I downloaded tomcat 6.0.35 and currently using this version only.

  2. Configured server.xml and added the following code -

    <Realm className="org.apache.catalina.realm.JNDIRealm" 
                       debug="99" 
                       connectionURL="ldap://server.domain.com:389/"  
                       userPattern="{0}" />
    
  3. server.xml 中注释了以下代码 -

    <!-- Commenting for LDAP
      <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
         resourceName="UserDatabase"/> -->
    
  4. article 中的步骤 2 和 3

  5. 有人建议有一些 jar 文件应该复制到 tomcat 以运行 ldap 身份验证,这是我需要做的吗?以及哪些 jar 文件?

  6. 另外,我肯定使用了正确的凭据,那么是什么导致了这个问题?

  7. 如果我使用了不正确的属性,有没有办法找出正确的 LDAP 属性?

最佳答案

以下代码使用纯 Java JNDI 从 LDAP 进行身份验证。原则是:-

  1. 首先使用管理员或 DN 用户查找用户。
  2. 用户对象需要使用用户凭据再次传递给 LDAP
  3. 无异常意味着 - 验证成功。其他身份验证失败。

代码片段

public static boolean authenticateJndi(String username, String password) throws Exception{
    Properties props = new Properties();
    props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    props.put(Context.PROVIDER_URL, "ldap://LDAPSERVER:PORT");
    props.put(Context.SECURITY_PRINCIPAL, "uid=adminuser,ou=special users,o=xx.com");//adminuser - User with special priviledge, dn user
    props.put(Context.SECURITY_CREDENTIALS, "adminpassword");//dn user password


    InitialDirContext context = new InitialDirContext(props);

    SearchControls ctrls = new SearchControls();
    ctrls.setReturningAttributes(new String[] { "givenName", "sn","memberOf" });
    ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE);

    NamingEnumeration<javax.naming.directory.SearchResult> answers = context.search("o=xx.com", "(uid=" + username + ")", ctrls);
    javax.naming.directory.SearchResult result = answers.nextElement();

    String user = result.getNameInNamespace();

    try {
        props = new Properties();
        props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        props.put(Context.PROVIDER_URL, "ldap://LDAPSERVER:PORT");
        props.put(Context.SECURITY_PRINCIPAL, user);
        props.put(Context.SECURITY_CREDENTIALS, password);

   context = new InitialDirContext(props);
    } catch (Exception e) {
        return false;
    }
    return true;
}

关于java - 使用 Java 的 LDAP 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12317205/

相关文章:

security - 如何使用 Javascript SDK authResponse 防止 "replay"

java - 应用程序用户身份验证java mongodb模块

security - 既然可以通过 ldap 进行身份验证和授权,为什么还要使用 kerberos?

java - LDAP 与 MYSQL..JA-SIG CAS 与 LDAP 对比 CAS 与 MySQL

java - 如何有效地为JPanel.add(component) 方法添加回调方法?

java - 在android中安排多个异步任务

java - Web 应用程序中的计划任务?

javascript - 带有 REST API 身份验证的 WebRTC 的 TURN 服务器

java - 检测 Java 9+ 运行时模块

Spring Security - 用于 Multi-Tenancy 应用程序的 OAuth、LDAP 集成