首页 > 解决方案 > Spring LDAP 获取 LDAP:错误代码 32 - 0000208D NO_OBJECT

问题描述

我终于能够编写一个独立的 java,我能够连接到 LDAP 并获​​取用户名,还能够进行身份验证(使用密码)。但是当我在 Spring LDAP 中尝试相同的 url 和其他详细信息时,我收到了错误。没有得到我在 Spring LDAP 中缺少的东西。请问有什么帮助吗???

LDAPService.java(独立)

public class LDAPService {
    private final static int ACCOUNT_DISABLED = 2;
    private static String[] ldapUrls = null;
    private static String adminId = null;
    private static String adminPassword  = null;
    private static SearchControls searchCtls = null; 
    private static String defaultGroup = null;
    private static LDAPService ldapService;
    private static String searchBase = null;

    private int domainIndex;
    private int domainCount;

    public static LDAPService getInstance() {
        if(ldapService == null ) ldapService = new LDAPService();
        return ldapService;
    }

    public LDAPService() {
        super();
        String ldapUrl = "ldap://mycompany-ldap-tdu.lb.xyz.dm.company.com:389/OU=Engine,OU=PQR%20Global,DC=am,DC=mds,DC=pqr,DC=com";
        ldapUrls = StringUtils.split(ldapUrl, ";");
        adminId = "CN=APP-XYZ-GRP,OU=Non-Person,OU=Users,OU=QWE,OU=Engine,OU=PQR Global,DC=am,DC=mds,DC=pqr,DC=com";
        adminPassword  = "admpasswd";
        defaultGroup = "85";
        searchBase = "";
        searchCtls = new SearchControls();
        String attrTemp = "distinguishedName,userPassword,memberOf,pwdLastSet,accountExpires,userAccountControl,givenName,sn";
        String returnedAtts[]= null;
        if(null != attrTemp){
            StringTokenizer st = new StringTokenizer(attrTemp,",");
            int size = st.countTokens();
            returnedAtts = new String[size];
            int counter = 0;
            while(st.hasMoreElements()){
                returnedAtts[counter++] = st.nextToken();
            }
        }
        int scope = 2;
        searchCtls.setReturningAttributes(returnedAtts);
        searchCtls.setSearchScope(scope);

        //Start with a random domain controller to balance load.
        Random randomGenerator = new Random();
        domainIndex = randomGenerator.nextInt(ldapUrls.length);
        domainCount = 0;


    }
    private Hashtable<String,String> getEnvironment(String userId, String password) {
        Hashtable<String,String> envDC = new Hashtable<String,String>();
        envDC.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
        envDC.put(Context.SECURITY_AUTHENTICATION,"simple");
        envDC.put(Context.PROVIDER_URL, ldapUrls[domainIndex]);
        envDC.put(Context.SECURITY_PRINCIPAL,userId);
        envDC.put(Context.SECURITY_CREDENTIALS,password);
        return envDC;
    }   


    public List<UserSecurityGroupId> authenticate(String userId,String password)throws Exception{
        List<UserSecurityGroupId> groups = null;
        String distinguishedName = null;
        String memberOf = null; 
        Long pwdLastSet = null;
        Long accountExpires = null;

        Hashtable<String,String> envGC = getEnvironment(adminId, adminPassword);
        String searchFilter = "(&(cn="+ userId + ")(objectClass=user))";

        try{
            LdapContext ctxGC = new InitialLdapContext(envGC,null);
            //search LDAP Server using search Filter.     
            NamingEnumeration answer = ctxGC.search(searchBase, searchFilter, searchCtls);
            if (answer.hasMoreElements()) {
                SearchResult result = (SearchResult)answer.next();
                Attributes attrs = result.getAttributes();
                // get all attributes if the user exists
                if (attrs != null) {
                    //Check if the User Account has been disabled
                    //This is identified by the returned values binary place holder for the decimal value 2 being a 1
                    if(null != attrs.get("useraccountcontrol")){
                        int userAccountControl = NumberUtils.toInt(attrs.get("useraccountcontrol")
                            .toString().replaceAll("userAccountControl: ", ""), ACCOUNT_DISABLED);
                        if((userAccountControl & ACCOUNT_DISABLED) == ACCOUNT_DISABLED){
                            return null;
                        }
                    }

                    //memberOf attribute retrieves the groups to which user belongs.
                    //only retrieve group memberships if password is provided
                    if(null != attrs.get("memberOf") && (null != password) && (password.trim().length() > 0)){
                        memberOf = attrs.get("memberOf").toString();
                    }
                    groups = getListOfGroups(memberOf, userId);
                    //pwdLastSet retrieves the time when password was last set.
                    if(null != attrs.get("pwdLastSet")){
                        pwdLastSet = new Long(attrs.get("pwdLastSet").get().toString());
                    }
                    //accountExpires retrieves the time when account will expire.
                    if(null != attrs.get("accountExpires")){
                        accountExpires = new Long(attrs.get("accountExpires").get().toString());
                        Calendar calendar = Calendar.getInstance();
                        calendar.clear();
                        calendar.set(1601, 0, 1, 0, 0);
                        accountExpires = accountExpires / 10000 + calendar.getTime().getTime();
                    }
                    //distinguished name retrieves the distinguished name for the user.
                    if(null != attrs.get("distinguishedName")){
                        distinguishedName = attrs.get("distinguishedName").get().toString();
                    }
                }
            }else{
                // if no attributes retrieved then user does not exist.
                throw new LoginException(LoginStatus.USER_NOT_EXIST.toString());
            }
            ctxGC.close();

            // verify if account is already expired.
            if ( (null != accountExpires) && (accountExpires.longValue() > 0)) {
                long today = System.currentTimeMillis();
                long expireDay = accountExpires.longValue();

                if ( expireDay < today ) {
                    throw new LoginException(LoginStatus.PASSWORD_EXPIRED.toString());
                }
            } 
        } catch (NamingException e) {
            System.out.println("Naming Exception occurred");
            if(checkNextDomainController())
                authenticate(userId, password);
            else
                throw new LoginException(LoginStatus.AUTHENTICATION_ERROR.toString());
        }

        if(null != distinguishedName){
            // verify the username and password if password is provided
            if((null != password) && (password.trim().length() > 0)){
                try {
                    Hashtable envDC = getEnvironment(distinguishedName,password);
                    DirContext ctx = new InitialDirContext(envDC);
                    ctx.close();
                    return groups;
                }catch (CommunicationException comEx){
                    System.out.println("Communication Exception occurred");
                    if(checkNextDomainController())
                        return authenticate(userId, password);
                    else
                        throw new LoginException(LoginStatus.AUTHENTICATION_ERROR.toString());
                }catch (AuthenticationException authEx){
                    authEx.printStackTrace();
                    System.out.println("Authentication Exception occurred");
                    throw new LoginException(LoginStatus.PASSWORD_INCORRECT.toString());
                }catch (NamingException nameEx){
                    System.out.println("Naming Exception occurred");
                    if(checkNextDomainController())
                        return authenticate(userId, password);
                    else
                        throw new LoginException(LoginStatus.AUTHENTICATION_ERROR.toString());
                }
            }else{
                return groups;
            }
        }else{
            throw new LoginException(LoginStatus.USER_NOT_EXIST.toString());
        }
    }

    private List<UserSecurityGroupId> getListOfGroups(String memberOf, String userId) {
        List<UserSecurityGroupId> userScrityGrpList = new ArrayList<UserSecurityGroupId>();
        String[] userSecurityGroupFilter = {"APP-XYZ"};
        if(null != memberOf){
            while(memberOf.indexOf("CN=") > 0){
                memberOf = memberOf.substring(memberOf.indexOf("CN=")+3);
                String tmp = memberOf.substring(0,memberOf.indexOf(','));
                if(StringUtils.startsWithAny(tmp, userSecurityGroupFilter )) {
                    UserSecurityGroupId groupId = new UserSecurityGroupId(userId, tmp);
                    userScrityGrpList.add(groupId);
                }
            }
        }
        UserSecurityGroupId group = new UserSecurityGroupId(userId, defaultGroup);
        if(!userScrityGrpList.contains(group)){
            userScrityGrpList.add(group);
        }
        return userScrityGrpList;
    }

    /**
     * This utility will return Associate Name from Active Directory corresponding to given user id.
     * @param userId
     * @return Associate Name
     */
    public String getAssociateName(String userId) {
        Hashtable<String,String> envGC = getEnvironment(adminId, adminPassword);
        String searchFilter = "(&(cn="+ userId + ")(objectClass=user))";
        String associateName = "";
        try{
            LdapContext ctxGC = new InitialLdapContext(envGC,null);
            //search LDAP Server using search Filter.     
            NamingEnumeration answer = ctxGC.search(searchBase, searchFilter, searchCtls);
            if (answer.hasMoreElements()) {
                SearchResult result = (SearchResult)answer.next();
                Attributes attrs = result.getAttributes();
                // get all attributes if the user exists
                if (attrs != null) {
                    //givenName attribute retrieves Given Name.
                    if(null != attrs.get("givenName") ){
                        associateName = associateName + attrs.get("givenName").get().toString() + " ";
                    }

                    //sn retrieves the Surname.
                    if(null != attrs.get("sn")){
                        associateName += attrs.get("sn").get().toString();
                    }
                    System.out.println(attrs.get("userPassword"));
                }
            }
            ctxGC.close();
        } catch (NamingException e) {
            System.out.println("Naming Exception occurred while retrieving associate name");
        }
        return associateName;
    }

    public static void main(String[] a) {
        LDAPService s = new LDAPService();
        try {
            System.out.println(s.getAssociateName("12345"));
            //System.out.println(s.authenticate("12345", "password123"));
        }catch(Exception e) {
            e.printStackTrace();
        }
    }

}

WebSecurityConfiguration.java(Spring 类)

@Configurable
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        try {

            auth.ldapAuthentication()
            .contextSource().url("ldap://mycompany-ldap-tdu.lb.xyz.dm.company.com:389/OU=Engine,OU=PQR%20Global,DC=am,DC=mds,DC=pqr,DC=com")
                .managerDn("CN=APP-XYZ-GRP,OU=Non-Person,OU=Users,OU=QWE,OU=Engine,OU=PQR Global,DC=am,DC=mds,DC=pqr,DC=com")
                .managerPassword("admpasswd")
            .and()
            .userSearchBase("")
            .groupSearchBase("")
            .userSearchFilter("(&(cn={0})(objectClass=user))")
            .groupSearchFilter("(member=userGroup)");
        }catch(Exception e) {
        e.printStackTrace();
    }
}

错误:

o.s.security.web.FilterChainProxy        : /account/login at position 7 of 14 in additional filter chain; firing Filter: 'DefaultLoginPageGeneratingFilter'
o.s.security.web.FilterChainProxy        : /account/login at position 8 of 14 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
o.s.s.w.a.www.BasicAuthenticationFilter  : Basic Authentication Authorization header found for user 'user'
o.s.s.authentication.ProviderManager     : Authentication attempt using org.springframework.security.ldap.authentication.LdapAuthenticationProvider
o.s.s.l.a.LdapAuthenticationProvider     : Processing authentication request for user: user
o.s.s.l.s.FilterBasedLdapUserSearch      : Searching for user 'user', with user search [ searchFilter: '(&(cn={0})(objectClass=user))', searchBase: '', scope: subtree, searchTimeLimit: 0, derefLinkFlag: false ]
.s.a.DefaultAuthenticationEventPublisher : No event was found for the exception org.springframework.security.authentication.InternalAuthenticationServiceException
o.s.s.w.a.www.BasicAuthenticationFilter  : Authentication request for failed: org.springframework.security.authentication.InternalAuthenticationServiceException: [LDAP: error code 32 - 0000208D: NameErr: DSID-0310020A, problem 2001 (NO_OBJECT), data 0, best match of:
        'DC=am,DC=mds,DC=pqr,DC=com'
    ]; nested exception is javax.naming.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-0310020A, problem 2001 (NO_OBJECT), data 0, best match of:
        'DC=am,DC=mds,DC=pqr,DC=com'
    ]; remaining name '/'
Trying to match using RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]
s.w.a.DelegatingAuthenticationEntryPoint : No match found. Using default entry point org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint@1dd945b2
w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed

标签: javaspring-bootspring-securityldapspring-ldap

解决方案


推荐阅读