it.geosolutions.geostore.services.rest.security.WebServiceTokenAuthenticationFilter.java Source code

Java tutorial

Introduction

Here is the source code for it.geosolutions.geostore.services.rest.security.WebServiceTokenAuthenticationFilter.java

Source

/* ====================================================================
 *
 * Copyright (C) 2015 GeoSolutions S.A.S.
 * http://www.geo-solutions.it
 *
 * GPLv3 + Classpath exception
 *
 * 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 2 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.
 *
 * ====================================================================
 *
 * This software consists of voluntary contributions made by developers
 * of GeoSolutions.  For more information on GeoSolutions, please see
 * <http://www.geo-solutions.it/>.
 *
 */
package it.geosolutions.geostore.services.rest.security;

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

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.log4j.Logger;
import org.springframework.security.core.Authentication;

/**
 * Token based authentication filter that looks for the token calling an external webservice.
 * 
 * The url of the service needs to be configured. A placeholder in the url will be replaced by
 * the actual token.
 * 
 * The result of the web service call will be parsed using given regular expression to:
 *  - check if the token is valid
 *  - extract the user name from the result
 * 
 * @author Mauro Bartolomeoli
 *
 */
public class WebServiceTokenAuthenticationFilter extends TokenAuthenticationFilter {

    private final static Logger LOGGER = Logger.getLogger(WebServiceTokenAuthenticationFilter.class);

    private String url;

    // compiled user search regex
    Pattern searchUserRegex = null;

    // connection timeout to the mapper web service (in seconds)
    long connectTimeout = 5;

    // read timeout to the mapper web service (in seconds)
    int readTimeout = 10;

    // optional external httpClient for web service connection (used mainly for tests)
    private HttpClient httpClient = null;

    public WebServiceTokenAuthenticationFilter(String url) {
        super();
        this.url = url;
    }

    /**
     * Regular expression to extract the username from the
     * webservice response.
     * 
     * The first group in the expression will be used for extraction.
     * 
     * @param searchUser
     */
    public void setSearchUser(String searchUser) {
        searchUserRegex = Pattern.compile(searchUser);
    }

    public void setConnectTimeout(long connectTimeout) {
        this.connectTimeout = connectTimeout;
    }

    public void setReadTimeout(int readTimeout) {
        this.readTimeout = readTimeout;
    }

    /**
     * Configures the HTTPClient implementation to be used to connect to the web service.
     * 
     * @param httpClient
     */
    public void setHttpClient(HttpClient httpClient) {
        this.httpClient = httpClient;
    }

    private HttpClient getHttpClient() {
        if (httpClient == null) {
            httpClient = new HttpClient();
        }
        return httpClient;
    }

    @Override
    protected Authentication checkToken(String token) {
        String webServiceUrl = url.replace("{token}", token);
        HttpClient client = getHttpClient();
        client.getParams().setParameter(HttpClientParams.CONNECTION_MANAGER_TIMEOUT, connectTimeout * 1000l);
        client.getParams().setParameter(HttpClientParams.SO_TIMEOUT, readTimeout * 1000);
        HttpMethod method = null;
        try {
            LOGGER.debug("Issuing request to webservice: " + url);
            method = new GetMethod(webServiceUrl);
            int statusCode = client.executeMethod(method);

            if (statusCode == HttpStatus.SC_OK) {
                // get response content as a single string, without new lines
                // so that is simpler to apply an extraction regular expression
                String response = method.getResponseBodyAsString().replace("\r", "").replace("\n", "");
                if (response != null) {
                    if (searchUserRegex == null) {
                        return createAuthenticationForUser(response, null, "");
                    } else {
                        Matcher matcher = searchUserRegex.matcher(response);
                        if (matcher.find()) {
                            return createAuthenticationForUser(matcher.group(1), null, response);
                        } else {
                            LOGGER.warn(
                                    "Error in getting username from webservice response cannot find userName in response");
                        }
                    }
                } else {
                    LOGGER.error("No response received from webservice: " + url);
                }
            }
        } catch (HttpException e) {
            LOGGER.error("Error contacting webservice: " + url, e);
        } catch (IOException e) {
            LOGGER.error("Error reading data from webservice: " + url, e);
        } finally {
            if (method != null) {
                method.releaseConnection();
            }
        }
        return null;

    }
}