com.orangeleap.common.security.OrangeLeapLdapUserSearch.java Source code

Java tutorial

Introduction

Here is the source code for com.orangeleap.common.security.OrangeLeapLdapUserSearch.java

Source

/*
 * Copyright (c) 2009. Orange Leap Inc. Active Constituent
 * Relationship Management Platform.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.orangeleap.common.security;

import javax.naming.directory.SearchControls;

import org.apache.commons.logging.Log;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
import org.springframework.security.ldap.LdapUserSearch;
import org.springframework.security.ldap.SpringSecurityLdapTemplate;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.util.Assert;

public class OrangeLeapLdapUserSearch implements LdapUserSearch {

    /**
     * Logger for this class and subclasses
     */
    protected final Log logger = OrangeLeapLogger.getLog(getClass());

    private ContextSource contextSource;

    /**
     * The LDAP SearchControls object used for the search. Shared between searches so shouldn't be modified once the bean has been configured.
     */
    private SearchControls searchControls = new SearchControls();

    /**
     * Context name to search in, relative to the base of the configured ContextSource.
     */
    private String searchBase = "";

    /**
     * The filter expression used in the user search. This is an LDAP search filter (as defined in 'RFC 2254') with optional arguments. See the documentation for the <tt>search</tt> methods in {@link javax.naming.directory.DirContext DirContext} for more information.
     * <p>
     * In this case, the username is the only parameter.
     * </p>
     * Possible examples are:
     * <ul>
     * <li>(uid={0}) - this would search for a username match on the uid attribute.</li>
     * </ul>
     */
    private String searchFilter;

    // ~ Constructors ===================================================================================================

    public OrangeLeapLdapUserSearch(String searchBase, String searchFilter,
            BaseLdapPathContextSource contextSource) {
        Assert.notNull(contextSource, "contextSource must not be null");
        Assert.notNull(searchFilter, "searchFilter must not be null.");
        Assert.notNull(searchBase, "searchBase must not be null (an empty string is acceptable).");

        this.searchFilter = searchFilter;
        this.contextSource = contextSource;
        this.searchBase = searchBase;

        setSearchSubtree(true);
    }

    public OrangeLeapLdapUserSearch(String searchFilter, BaseLdapPathContextSource contextSource) {
        Assert.notNull(contextSource, "contextSource must not be null");
        Assert.notNull(searchFilter, "searchFilter must not be null.");

        this.searchFilter = searchFilter;
        this.contextSource = contextSource;

        setSearchSubtree(true);
    }

    // ~ Methods ========================================================================================================

    /**
     * Return the LdapUserDetails containing the user's information
     *
     * @param username the username to search for.
     * @return An LdapUserDetails object containing the details of the located user's directory entry
     * @throws UsernameNotFoundException if no matching entry is found.
     */
    public DirContextOperations searchForUser(String username) {
        SpringSecurityLdapTemplate template = new SpringSecurityLdapTemplate(contextSource);

        template.setSearchControls(searchControls);

        try {

            String[] filterArgs;
            String aSearchBase;

            if (username.indexOf("@") > -1) {
                String[] split = username.split("@");
                filterArgs = new String[] { split[0] };
                aSearchBase = "o=" + split[1];
            } else {
                filterArgs = new String[] { username };
                aSearchBase = searchBase;
            }

            return template.searchForSingleEntry(aSearchBase, searchFilter, filterArgs);

        } catch (IncorrectResultSizeDataAccessException notFound) {
            if (notFound.getActualSize() == 0) {
                throw new UsernameNotFoundException("User " + username + " not found in directory.", username);
            }
            // Search should never return multiple results if properly configured, so just rethrow
            throw notFound;
        }
    }

    /**
     * Return the LdapUserDetails containing the user's information
     *
     * @param username the username to search for.
     * @return An LdapUserDetails object containing the details of the located user's directory entry
     * @throws UsernameNotFoundException if no matching entry is found.
     */
    public DirContextOperations searchForUser(String username, String site) {
        SpringSecurityLdapTemplate template = new SpringSecurityLdapTemplate(contextSource);

        template.setSearchControls(searchControls);

        try {
            String searchBase = "o=" + site;
            return template.searchForSingleEntry(searchBase, searchFilter, new String[] { username });

        } catch (IncorrectResultSizeDataAccessException notFound) {
            if (notFound.getActualSize() == 0) {
                throw new UsernameNotFoundException("User " + username + " not found in directory.", username);
            }
            // Search should never return multiple results if properly configured, so just rethrow
            throw notFound;
        }
    }

    /**
     * Sets the corresponding property on the {@link SearchControls} instance used in the search.
     *
     * @param deref the derefLinkFlag value as defined in SearchControls..
     */
    public void setDerefLinkFlag(boolean deref) {
        searchControls.setDerefLinkFlag(deref);
    }

    /**
     * If true then searches the entire subtree as identified by context, if false (the default) then only searches the level identified by the context.
     *
     * @param searchSubtree true the underlying search controls should be set to SearchControls.SUBTREE_SCOPE rather than SearchControls.ONELEVEL_SCOPE.
     */
    public void setSearchSubtree(boolean searchSubtree) {
        searchControls.setSearchScope(searchSubtree ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE);
    }

    /**
     * The time to wait before the search fails; the default is zero, meaning forever.
     *
     * @param searchTimeLimit the time limit for the search (in milliseconds).
     */
    public void setSearchTimeLimit(int searchTimeLimit) {
        searchControls.setTimeLimit(searchTimeLimit);
    }

    /**
     * Specifies the attributes that will be returned as part of the search.
     * <p/>
     * null indicates that all attributes will be returned. An empty array indicates no attributes are returned.
     *
     * @param attrs An array of attribute names identifying the attributes that will be returned. Can be null.
     */
    public void setReturningAttributes(String[] attrs) {
        searchControls.setReturningAttributes(attrs);
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();

        sb.append("[ searchFilter: '").append(searchFilter).append("', ");
        sb.append("searchBase: '").append(searchBase).append("'");
        sb.append(", scope: ").append(
                searchControls.getSearchScope() == SearchControls.SUBTREE_SCOPE ? "subtree" : "single-level, ");
        sb.append(", searchTimeLimit: ").append(searchControls.getTimeLimit());
        sb.append(", derefLinkFlag: ").append(searchControls.getDerefLinkFlag()).append(" ]");
        return sb.toString();
    }
}