org.dspace.service.impl.ClientInfoServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.dspace.service.impl.ClientInfoServiceImpl.java

Source

/**
 * The contents of this file are subject to the license and copyright
 * detailed in the LICENSE and NOTICE files at the root of the source
 * tree and available online at
 *
 * http://www.dspace.org/license/
 */
package org.dspace.service.impl;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.dspace.service.ClientInfoService;
import org.dspace.services.ConfigurationService;
import org.dspace.statistics.util.IPTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * Implementation of {@link ClientInfoService} that can provide information on DSpace client requests
 *
 * @author tom dot desair at gmail dot com
 */
public class ClientInfoServiceImpl implements ClientInfoService {

    private static final String X_FORWARDED_FOR_HEADER = "X-Forwarded-For";

    private static final Logger log = LoggerFactory.getLogger(ClientInfoServiceImpl.class);

    private Boolean useProxiesEnabled;

    private ConfigurationService configurationService;

    /**
     * Sparse HashTable structure to hold IP address ranges of trusted proxies
     */
    private IPTable trustedProxies;

    @Autowired(required = true)
    public ClientInfoServiceImpl(ConfigurationService configurationService) {
        this.configurationService = configurationService;
        this.trustedProxies = parseTrustedProxyRanges(
                configurationService.getArrayProperty("proxies.trusted.ipranges"));
    }

    @Override
    public String getClientIp(HttpServletRequest request) {
        return getClientIp(request.getRemoteAddr(), request.getHeader(X_FORWARDED_FOR_HEADER));
    }

    @Override
    public String getClientIp(String remoteIp, String xForwardedForHeaderValue) {
        String ip = remoteIp;

        if (isUseProxiesEnabled()) {
            String xForwardedForIp = getXForwardedForIpValue(remoteIp, xForwardedForHeaderValue);

            if (StringUtils.isNotBlank(xForwardedForIp) && isRequestFromTrustedProxy(ip)) {
                ip = xForwardedForIp;
            }

        } else if (StringUtils.isNotBlank(xForwardedForHeaderValue)) {
            log.warn("X-Forwarded-For header detected but useProxiesEnabled is not enabled. "
                    + "If your dspace is behind a proxy set it to true");
        }

        return ip;
    }

    @Override
    public boolean isUseProxiesEnabled() {
        if (useProxiesEnabled == null) {
            useProxiesEnabled = configurationService.getBooleanProperty("useProxies", true);
            log.info("useProxies=" + useProxiesEnabled);
        }

        return useProxiesEnabled;
    }

    private IPTable parseTrustedProxyRanges(String[] proxyProperty) {
        if (ArrayUtils.isEmpty(proxyProperty)) {
            return null;
        } else {
            //Load all supplied proxy IP ranges into the IP table
            IPTable ipTable = new IPTable();
            try {
                for (String proxyRange : proxyProperty) {
                    ipTable.add(proxyRange);
                }
            } catch (IPTable.IPFormatException e) {
                log.error("Property proxies.trusted.ipranges contains an invalid IP range", e);
                ipTable = null;
            }

            return ipTable;
        }
    }

    private boolean isRequestFromTrustedProxy(String ipAddress) {
        try {
            return trustedProxies == null || trustedProxies.contains(ipAddress);
        } catch (IPTable.IPFormatException e) {
            log.error("Request contains invalid remote address", e);
            return false;
        }
    }

    private String getXForwardedForIpValue(String remoteIp, String xForwardedForValue) {
        String ip = null;

        /* This header is a comma delimited list */
        String headerValue = StringUtils.trimToEmpty(xForwardedForValue);
        for (String xfip : headerValue.split(",")) {
            /* proxy itself will sometime populate this header with the same value in
               remote address. ordering in spec is vague, we'll just take the last
               not equal to the proxy
            */
            if (!StringUtils.equals(remoteIp, xfip) && StringUtils.isNotBlank(xfip)
            //if we have trusted proxies, we'll assume that they are not the client IP
                    && (trustedProxies == null || !isRequestFromTrustedProxy(xfip))) {

                ip = xfip.trim();
            }
        }

        return ip;
    }
}