org.georchestra.security.LdapUserDetailsRequestHeaderProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.georchestra.security.LdapUserDetailsRequestHeaderProvider.java

Source

/*
 * Copyright (C) 2009-2016 by the geOrchestra PSC
 *
 * This file is part of geOrchestra.
 *
 * geOrchestra 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.
 *
 * geOrchestra 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
 * geOrchestra.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.georchestra.security;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.naming.NamingEnumeration;
import javax.naming.directory.Attribute;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Header;
import org.apache.http.message.BasicHeader;
import org.georchestra.commons.configuration.GeorchestraConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
import org.springframework.security.ldap.search.LdapUserSearch;
import org.springframework.util.Assert;

/**
 * Reads information from a user node in LDAP and adds the information as
 * headers to the request.
 *
 * @author jeichar
 */
public class LdapUserDetailsRequestHeaderProvider extends HeaderProvider {

    protected static final Log logger = LogFactory
            .getLog(LdapUserDetailsRequestHeaderProvider.class.getPackage().getName());

    private LdapUserSearch _userSearch;
    private Map<String, String> _headerMapping;
    private Pattern pattern;

    @Autowired
    private GeorchestraConfiguration georchestraConfiguration;

    public LdapUserDetailsRequestHeaderProvider(LdapUserSearch userSearch, String orgsSearchBaseDN,
            Map<String, String> headerMapping) {
        Assert.notNull(userSearch, "userSearch must not be null");
        Assert.notNull(headerMapping, "headerMapping must not be null");
        this._userSearch = userSearch;
        this._headerMapping = headerMapping;

        this.pattern = Pattern.compile("([^=,]+)=([^=,]+)," + orgsSearchBaseDN + ".*");
    }

    public void init() throws IOException {
        if ((georchestraConfiguration != null) && (georchestraConfiguration.activated())) {
            Properties pHmap = georchestraConfiguration.loadCustomPropertiesFile("headers-mapping");
            _headerMapping.clear();
            for (String key : pHmap.stringPropertyNames()) {
                _headerMapping.put(key, pHmap.getProperty(key));
            }
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    protected Collection<Header> getCustomRequestHeaders(HttpSession session, HttpServletRequest originalRequest) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication instanceof AnonymousAuthenticationToken) {
            return Collections.emptyList();
        }
        String username = authentication.getName();
        DirContextOperations userData;

        Collection<Header> headers = Collections.emptyList();

        synchronized (session) {

            if (session.getAttribute("security-proxy-cached-attrs") != null) {
                try {
                    headers = (Collection<Header>) session.getAttribute("security-proxy-cached-attrs");
                    String expectedUsername = (String) session.getAttribute("security-proxy-cached-username");

                    if (username.equals(expectedUsername)) {
                        return headers;
                    }
                } catch (Exception e) {
                    logger.info("Unable to lookup cached user's attributes for user :" + username, e);
                }
            } else {
                try {
                    userData = _userSearch.searchForUser(username);
                } catch (Exception e) {
                    logger.info("Unable to lookup user:" + username, e);
                    return Collections.emptyList();
                }
                headers = new ArrayList<Header>();
                for (Map.Entry<String, String> entry : _headerMapping.entrySet()) {
                    try {
                        Attribute attributes = userData.getAttributes().get(entry.getValue());
                        if (attributes != null) {
                            NamingEnumeration<?> all = attributes.getAll();
                            StringBuilder value = new StringBuilder();
                            while (all.hasMore()) {
                                if (value.length() > 0) {
                                    value.append(',');
                                }
                                value.append(all.next());
                            }
                            headers.add(new BasicHeader(entry.getKey(), value.toString()));
                        }
                    } catch (javax.naming.NamingException e) {
                        logger.error("problem adding headers for request:" + entry.getKey(), e);
                    }
                }

                // Add user organization
                try {
                    // Retreive memberOf attributes
                    String[] attrs = { "memberOf" };
                    ((FilterBasedLdapUserSearch) this._userSearch).setReturningAttributes(attrs);
                    userData = _userSearch.searchForUser(username);
                    Attribute attributes = userData.getAttributes().get("memberOf");
                    if (attributes != null) {
                        NamingEnumeration<?> all = attributes.getAll();

                        while (all.hasMore()) {
                            String memberOf = all.next().toString();
                            Matcher m = this.pattern.matcher(memberOf);
                            if (m.matches()) {
                                headers.add(new BasicHeader("sec-org", m.group(2)));
                                break;
                            }
                        }
                    }
                } catch (javax.naming.NamingException e) {
                    logger.error("problem adding headers for request: organization", e);
                } finally {
                    // restore standard attribute list
                    ((FilterBasedLdapUserSearch) this._userSearch).setReturningAttributes(null);
                }

                logger.info("Storing attributes into session for user :" + username);
                session.setAttribute("security-proxy-cached-username", username);
                session.setAttribute("security-proxy-cached-attrs", headers);
            }
        }

        return headers;
    }
}