org.codehaus.plexus.redback.authentication.ldap.LdapBindAuthenticator.java Source code

Java tutorial

Introduction

Here is the source code for org.codehaus.plexus.redback.authentication.ldap.LdapBindAuthenticator.java

Source

package org.codehaus.plexus.redback.authentication.ldap;

/*
 * Copyright 2005 The Codehaus.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import org.apache.commons.lang.StringUtils;
import org.codehaus.plexus.redback.authentication.AuthenticationDataSource;
import org.codehaus.plexus.redback.authentication.AuthenticationException;
import org.codehaus.plexus.redback.authentication.AuthenticationResult;
import org.codehaus.plexus.redback.authentication.Authenticator;
import org.codehaus.plexus.redback.authentication.PasswordBasedAuthenticationDataSource;
import org.codehaus.plexus.redback.common.ldap.UserMapper;
import org.codehaus.plexus.redback.common.ldap.connection.LdapConnection;
import org.codehaus.plexus.redback.common.ldap.connection.LdapConnectionFactory;
import org.codehaus.plexus.redback.common.ldap.connection.LdapException;
import org.codehaus.plexus.redback.configuration.UserConfiguration;
import org.codehaus.plexus.redback.users.ldap.service.LdapCacheService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.inject.Inject;
import javax.inject.Named;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

/**
 * LdapBindAuthenticator:
 *
 * @author: Jesse McConnell <jesse@codehaus.org>
 * @version: $Id$
 */
@Service("authenticator#ldap")
public class LdapBindAuthenticator implements Authenticator {

    private Logger log = LoggerFactory.getLogger(getClass());

    @Inject
    @Named(value = "userMapper#ldap")
    private UserMapper mapper;

    @Inject
    @Named(value = "ldapConnectionFactory#configurable")
    private LdapConnectionFactory connectionFactory;

    @Inject
    @Named(value = "userConfiguration")
    private UserConfiguration config;

    @Inject
    private LdapCacheService ldapCacheService;

    public String getId() {
        return "LdapBindAuthenticator";
    }

    public AuthenticationResult authenticate(AuthenticationDataSource s) throws AuthenticationException {
        PasswordBasedAuthenticationDataSource source = (PasswordBasedAuthenticationDataSource) s;

        if (!config.getBoolean("ldap.bind.authenticator.enabled")
                || (!config.getBoolean("ldap.bind.authenticator.allowEmptyPasswords", false)
                        && StringUtils.isEmpty(source.getPassword()))) {
            return new AuthenticationResult(false, source.getPrincipal(), null);
        }

        SearchControls ctls = new SearchControls();

        ctls.setCountLimit(1);

        ctls.setDerefLinkFlag(true);
        ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);

        String filter = "(&(objectClass=" + mapper.getUserObjectClass() + ")"
                + (mapper.getUserFilter() != null ? mapper.getUserFilter() : "") + "(" + mapper.getUserIdAttribute()
                + "=" + source.getPrincipal() + "))";

        log.info("Searching for users with filter: \'{}\'" + " from base dn: {}", filter, mapper.getUserBaseDn());

        LdapConnection ldapConnection = getLdapConnection();
        LdapConnection authLdapConnection = null;
        NamingEnumeration<SearchResult> results = null;
        try {
            // check the cache for user's userDn in the ldap server
            String userDn = ldapCacheService.getLdapUserDn(source.getPrincipal());

            if (userDn == null) {
                log.debug("userDn for user {} not found in cache. Retrieving from ldap server..",
                        source.getPrincipal());

                DirContext context = ldapConnection.getDirContext();

                results = context.search(mapper.getUserBaseDn(), filter, ctls);

                log.info("Found user?: {}", results.hasMoreElements());

                if (results.hasMoreElements()) {
                    SearchResult result = results.nextElement();

                    userDn = result.getNameInNamespace();

                    log.debug("Adding userDn {} for user {} to the cache..", userDn, source.getPrincipal());

                    // REDBACK-289/MRM-1488 cache the ldap user's userDn to lessen calls to ldap server
                    ldapCacheService.addLdapUserDn(source.getPrincipal(), userDn);
                } else {
                    return new AuthenticationResult(false, source.getPrincipal(), null);
                }
            }

            log.info("Attempting Authenication: + {}", userDn);

            authLdapConnection = connectionFactory.getConnection(userDn, source.getPassword());

            return new AuthenticationResult(true, source.getPrincipal(), null);
        } catch (LdapException e) {
            return new AuthenticationResult(false, source.getPrincipal(), e);
        } catch (NamingException e) {
            return new AuthenticationResult(false, source.getPrincipal(), e);
        } finally {
            closeNamingEnumeration(results);
            closeLdapConnection(ldapConnection);
            if (authLdapConnection != null) {
                closeLdapConnection(authLdapConnection);
            }
        }
    }

    public boolean supportsDataSource(AuthenticationDataSource source) {
        return (source instanceof PasswordBasedAuthenticationDataSource);
    }

    private LdapConnection getLdapConnection() {
        try {
            return connectionFactory.getConnection();
        } catch (LdapException e) {
            log.warn("failed to get a ldap connection " + e.getMessage(), e);
            throw new RuntimeException("failed to get a ldap connection " + e.getMessage(), e);
        }
    }

    private void closeLdapConnection(LdapConnection ldapConnection) {
        if (ldapConnection != null) {
            ldapConnection.close();
        }
    }

    private void closeNamingEnumeration(NamingEnumeration<SearchResult> results) {
        try {
            if (results != null) {
                results.close();
            }
        } catch (NamingException e) {
            log.warn("skip exception closing naming search result " + e.getMessage());
        }
    }
}