使用Java中的服务帐户进行LDAP身份验证

使用Java中的服务帐户进行LDAP身份验证,java,authentication,ldap,Java,Authentication,Ldap,我正在尝试使用创建的服务帐户对LDAP中的用户进行身份验证。在ctx=new InitialDirContext(env)上,Im出现以下错误 [LDAP:错误代码49-8009030C:LDAPPER:DSID-0C09003A8,注释:AcceptSecurityContext错误,数据2030,v1db1 有人能帮我了解我哪里出了问题吗? 这是我的java文件 /** * */ package com.dei; import java.util.Hashtable; import

我正在尝试使用创建的服务帐户对LDAP中的用户进行身份验证。在ctx=new InitialDirContext(env)上,Im出现以下错误

[LDAP:错误代码49-8009030C:LDAPPER:DSID-0C09003A8,注释:AcceptSecurityContext错误,数据2030,v1db1

有人能帮我了解我哪里出了问题吗?

这是我的java文件

/**
 * 
 */
package com.dei;

import java.util.Hashtable;

import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.SizeLimitExceededException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

public class LdapConnector {


        private static final String LDAP_SERVER_PORT = "389";
        private static final String LDAP_SERVER = "server";
        private static final String LDAP_BASE_DN = "OU=role,OU=roles,OU=de,OU=apps,DC=meta,DC=company,DC=com";
        private static final String LDAP_BIND_DN = "cn=service_account";//service account userid provided by LDAP team
        private static final String LDAP_BIND_PASSWORD = "password";///service account pwd provided by LDAP team


        public Boolean validateLogin(String userName, String userPassword) {
            Hashtable<String, String> env = new Hashtable<String, String>();
            env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
            env.put(Context.PROVIDER_URL, "ldap://" + LDAP_SERVER + ":" + LDAP_SERVER_PORT + "/" + LDAP_BASE_DN);

            // To get rid of the PartialResultException when using Active Directory
            env.put(Context.REFERRAL, "follow");

            // Needed for the Bind (User Authorized to Query the LDAP server) 
            env.put(Context.SECURITY_AUTHENTICATION, "simple");
            env.put(Context.SECURITY_PRINCIPAL, LDAP_BIND_DN);
            env.put(Context.SECURITY_CREDENTIALS, LDAP_BIND_PASSWORD);

            DirContext ctx;
            try {
               ctx = new InitialDirContext(env);
            } catch (NamingException e) {
               throw new RuntimeException(e);
            }

            NamingEnumeration<SearchResult> results = null;

            try {
               SearchControls controls = new SearchControls();
               controls.setSearchScope(SearchControls.SUBTREE_SCOPE); // Search Entire Subtree
               controls.setCountLimit(1);   //Sets the maximum number of entries to be returned as a result of the search
               controls.setTimeLimit(5000); // Sets the time limit of these SearchControls in milliseconds

               String searchString = "(&(objectCategory=user)(sAMAccountName=" + userName + "))";

               results = ctx.search("", searchString, controls);

               if (results.hasMore()) {

                   SearchResult result = (SearchResult) results.next();
                   Attributes attrs = result.getAttributes();
                   Attribute dnAttr = attrs.get("distinguishedName");
                   String dn = (String) dnAttr.get();

                   // User Exists, Validate the Password

                   env.put(Context.SECURITY_PRINCIPAL, dn);
                   env.put(Context.SECURITY_CREDENTIALS, userPassword);

                   new InitialDirContext(env); // Exception will be thrown on Invalid case
                   System.out.println("Login successful");
                   return true;
               } 
               else 
                   return false;

            } catch (AuthenticationException e) { // Invalid Login
                System.out.println("Login failed" +e.getMessage());

                return false;
            } catch (NameNotFoundException e) { // The base context was not found.
                System.out.println("Login failed" +e.getMessage());
                return false;
            } catch (SizeLimitExceededException e) {
                throw new RuntimeException("LDAP Query Limit Exceeded, adjust the query to bring back less records", e);
            } catch (NamingException e) {
               throw new RuntimeException(e);
            } finally {

               if (results != null) {
                  try { results.close(); } catch (Exception e) { /* Do Nothing */ }
               }

               if (ctx != null) {
                  try { ctx.close(); } catch (Exception e) { /* Do Nothing */ }
               }
            }
        }
}
/**
* 
*/
包com.dei;
导入java.util.Hashtable;
导入javax.naming.AuthenticationException;
导入javax.naming.Context;
导入javax.naming.NameNotFoundException;
导入javax.naming.NamingEnumeration;
导入javax.naming.NamingException;
导入javax.naming.sizelimiteExceedeException;
导入javax.naming.directory.Attribute;
导入javax.naming.directory.Attributes;
导入javax.naming.directory.DirContext;
导入javax.naming.directory.InitialDirContext;
导入javax.naming.directory.SearchControls;
导入javax.naming.directory.SearchResult;
公共类LDA连接器{
私有静态最终字符串LDAP\u SERVER\u PORT=“389”;
私有静态最终字符串LDAP_SERVER=“SERVER”;
私有静态最终字符串LDAP_BASE_DN=“OU=role,OU=roles,OU=de,OU=apps,DC=meta,DC=company,DC=com”;
私有静态最终字符串LDAP\u BIND\u DN=“cn=service\u account”;//LDAP团队提供的service account userid
私有静态最终字符串LDAP\u BIND\u PASSWORD=“PASSWORD”///由LDAP团队提供的服务帐户pwd
公共布尔validateLogin(字符串用户名、字符串用户密码){
Hashtable env=新的Hashtable();
put(Context.INITIAL\u Context\u工厂,“com.sun.jndi.ldap.LdapCtxFactory”);
环境put(Context.PROVIDER_URL,“ldap://”+ldap_SERVER+:“+ldap_SERVER_PORT+”/“+ldap_BASE_DN);
//使用Active Directory时消除PartialResultException的步骤
环境投入(Context.reference,“follow”);
//绑定所需(有权查询LDAP服务器的用户)
环境put(Context.SECURITY_认证,“simple”);
环境put(Context.SECURITY\u PRINCIPAL,LDAP\u BIND\u DN);
环境put(Context.SECURITY\u凭证、LDAP\u绑定\u密码);
dirctx;
试一试{
ctx=新的初始目录上下文(env);
}捕获(NamingE例外){
抛出新的运行时异常(e);
}
NamingEnumeration结果=空;
试一试{
SearchControls=新的SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);//搜索整个子树
controls.setCountLimit(1);//设置作为搜索结果返回的最大条目数
controls.setTimeLimit(5000);//以毫秒为单位设置这些SearchControl的时间限制
字符串searchString=“(&(objectCategory=user)(sAMAccountName=“+userName+”));
结果=ctx.search(“,searchString,controls);
if(results.hasMore()){
SearchResult=(SearchResult)results.next();
Attributes attrs=result.getAttributes();
属性dnAttr=attrs.get(“DifferentizedName”);
字符串dn=(字符串)dnAttr.get();
//用户已存在,请验证密码
环境put(Context.SECURITY_PRINCIPAL,dn);
env.put(Context.SECURITY\u凭证、用户密码);
new InitialDirContext(env);//将对无效的大小写引发异常
System.out.println(“登录成功”);
返回true;
} 
其他的
返回false;
}catch(AuthenticationException e){//登录无效
System.out.println(“登录失败”+e.getMessage());
返回false;
}catch(NameNotFoundException){//未找到基上下文。
System.out.println(“登录失败”+e.getMessage());
返回false;
}捕获(SizeLimitExceedeException e){
抛出新的RuntimeException(“超过LDAP查询限制,调整查询以带回更少的记录”,e);
}捕获(NamingE例外){
抛出新的运行时异常(e);
}最后{
如果(结果!=null){
尝试{results.close();}catch(异常e){/*不执行任何操作*/}
}
如果(ctx!=null){
请尝试{ctx.close();}捕获(异常e){/*不执行任何操作*/}
}
}
}
}

错误49表示无效凭据,但诊断字符串“AcceptSecurityContext error,data 2030”表示“没有此类对象”,即在目录中找不到LDAP\u BIND\u DN“cn=service\u account”。
我猜“cn=service\u account”不是该帐户的完整DN。

绑定操作失败,通常是由于该帐户出现问题


确保用于连接LDAP服务器的绑定帐户的凭据正确。错误代码数据2030表示用户的DN无效。

我想我们这里打印错误。“我的客人”可能是指“我的猜测”