mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-14 05:23:14 +00:00
DS-3542: Only trust X-Forwared-For headers from trusted proxies
This commit is contained in:
@@ -18,13 +18,14 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.core.factory.CoreServiceFactory;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.Group;
|
||||
import org.dspace.eperson.factory.EPersonServiceFactory;
|
||||
import org.dspace.eperson.service.GroupService;
|
||||
import org.dspace.service.ClientInfoService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
|
||||
/**
|
||||
@@ -67,6 +68,7 @@ public class IPAuthentication implements AuthenticationMethod {
|
||||
protected List<IPMatcher> ipNegativeMatchers;
|
||||
|
||||
protected GroupService groupService;
|
||||
protected ClientInfoService clientInfoService;
|
||||
|
||||
|
||||
/**
|
||||
@@ -91,6 +93,7 @@ public class IPAuthentication implements AuthenticationMethod {
|
||||
ipMatcherGroupIDs = new HashMap<>();
|
||||
ipMatcherGroupNames = new HashMap<>();
|
||||
groupService = EPersonServiceFactory.getInstance().getGroupService();
|
||||
clientInfoService = CoreServiceFactory.getInstance().getClientInfoService();
|
||||
|
||||
List<String> propNames = DSpaceServicesFactory.getInstance().getConfigurationService()
|
||||
.getPropertyKeys("authentication-ip");
|
||||
@@ -169,18 +172,7 @@ public class IPAuthentication implements AuthenticationMethod {
|
||||
List<Group> groups = new ArrayList<Group>();
|
||||
|
||||
// Get the user's IP address
|
||||
String addr = request.getRemoteAddr();
|
||||
if (useProxies == null) {
|
||||
useProxies = ConfigurationManager.getBooleanProperty("useProxies", false);
|
||||
}
|
||||
if (useProxies && request.getHeader("X-Forwarded-For") != null) {
|
||||
/* This header is a comma delimited list */
|
||||
for (String xfip : request.getHeader("X-Forwarded-For").split(",")) {
|
||||
if (!request.getHeader("X-Forwarded-For").contains(addr)) {
|
||||
addr = xfip.trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
String addr = clientInfoService.getClientIp(request);
|
||||
|
||||
for (IPMatcher ipm : ipMatchers) {
|
||||
try {
|
||||
|
@@ -10,6 +10,7 @@ package org.dspace.core.factory;
|
||||
import org.dspace.core.service.LicenseService;
|
||||
import org.dspace.core.service.NewsService;
|
||||
import org.dspace.core.service.PluginService;
|
||||
import org.dspace.service.ClientInfoService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
|
||||
/**
|
||||
@@ -26,6 +27,8 @@ public abstract class CoreServiceFactory {
|
||||
|
||||
public abstract PluginService getPluginService();
|
||||
|
||||
public abstract ClientInfoService getClientInfoService();
|
||||
|
||||
public static CoreServiceFactory getInstance() {
|
||||
return DSpaceServicesFactory.getInstance().getServiceManager()
|
||||
.getServiceByName("coreServiceFactory", CoreServiceFactory.class);
|
||||
|
@@ -10,6 +10,7 @@ package org.dspace.core.factory;
|
||||
import org.dspace.core.service.LicenseService;
|
||||
import org.dspace.core.service.NewsService;
|
||||
import org.dspace.core.service.PluginService;
|
||||
import org.dspace.service.ClientInfoService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
@@ -29,6 +30,9 @@ public class CoreServiceFactoryImpl extends CoreServiceFactory {
|
||||
@Autowired(required = true)
|
||||
private PluginService pluginService;
|
||||
|
||||
@Autowired(required = true)
|
||||
private ClientInfoService clientInfoService;
|
||||
|
||||
@Override
|
||||
public LicenseService getLicenseService() {
|
||||
return licenseService;
|
||||
@@ -43,4 +47,8 @@ public class CoreServiceFactoryImpl extends CoreServiceFactory {
|
||||
public PluginService getPluginService() {
|
||||
return pluginService;
|
||||
}
|
||||
|
||||
public ClientInfoService getClientInfoService() {
|
||||
return clientInfoService;
|
||||
}
|
||||
}
|
||||
|
@@ -25,8 +25,8 @@ import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.service.ClientInfoService;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.model.Event;
|
||||
import org.dspace.usage.AbstractUsageEventListener;
|
||||
@@ -50,6 +50,7 @@ public class GoogleRecorderEventListener extends AbstractUsageEventListener {
|
||||
|
||||
protected ContentServiceFactory contentServiceFactory;
|
||||
protected ConfigurationService configurationService;
|
||||
protected ClientInfoService clientInfoService;
|
||||
|
||||
public GoogleRecorderEventListener() {
|
||||
// httpclient is threadsafe so we only need one.
|
||||
@@ -62,10 +63,15 @@ public class GoogleRecorderEventListener extends AbstractUsageEventListener {
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setConfigurationService(final ConfigurationService configurationService) {
|
||||
public void setConfigurationService(ConfigurationService configurationService) {
|
||||
this.configurationService = configurationService;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setClientInfoService(ClientInfoService clientInfoService) {
|
||||
this.clientInfoService = clientInfoService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveEvent(Event event) {
|
||||
if ((event instanceof UsageEvent)) {
|
||||
@@ -187,22 +193,7 @@ public class GoogleRecorderEventListener extends AbstractUsageEventListener {
|
||||
}
|
||||
|
||||
private String getIPAddress(HttpServletRequest request) {
|
||||
String clientIP = request.getRemoteAddr();
|
||||
if (ConfigurationManager.getBooleanProperty("useProxies", false) && request
|
||||
.getHeader("X-Forwarded-For") != null) {
|
||||
/* This header is a comma delimited list */
|
||||
for (String xfip : request.getHeader("X-Forwarded-For").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 (!request.getHeader("X-Forwarded-For").contains(clientIP)) {
|
||||
clientIP = xfip.trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return clientIP;
|
||||
return clientInfoService.getClientIp(request);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Service that can be used to retrieve information about DSpace clients
|
||||
*/
|
||||
public interface ClientInfoService {
|
||||
|
||||
/**
|
||||
* Get the client IP of this request taking into account the X-Forwarded-For header and the "useProxies" setting
|
||||
* @param request The client HTTP request
|
||||
* @return The IP address of the originating client
|
||||
*/
|
||||
String getClientIp(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* Get the client IP of this request taking into account the X-Forwarded-For header and the "useProxies" setting
|
||||
* @param remoteIp the remote address of the current request
|
||||
* @param xForwardedForHeaderValue The value of the X-Forwarded-For header
|
||||
* @return The IP address of the originating client
|
||||
*/
|
||||
String getClientIp(String remoteIp, String xForwardedForHeaderValue);
|
||||
|
||||
/**
|
||||
* Does DSpace take into account HTTP proxy headers or not
|
||||
* @return true if this is the case, false otherwise
|
||||
*/
|
||||
boolean isUseProxiesEnabled();
|
||||
}
|
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
@@ -82,6 +82,7 @@ import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.Group;
|
||||
import org.dspace.service.ClientInfoService;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.statistics.service.SolrLoggerService;
|
||||
import org.dspace.statistics.util.DnsLookup;
|
||||
@@ -115,8 +116,6 @@ public class SolrLoggerServiceImpl implements SolrLoggerService, InitializingBea
|
||||
|
||||
protected DatabaseReader locationService;
|
||||
|
||||
protected boolean useProxies;
|
||||
|
||||
private static List<String> statisticYearCores = new ArrayList<String>();
|
||||
private static boolean statisticYearCoresInit = false;
|
||||
|
||||
@@ -126,6 +125,8 @@ public class SolrLoggerServiceImpl implements SolrLoggerService, InitializingBea
|
||||
protected ContentServiceFactory contentServiceFactory;
|
||||
@Autowired(required = true)
|
||||
private ConfigurationService configurationService;
|
||||
@Autowired(required = true)
|
||||
private ClientInfoService clientInfoService;
|
||||
|
||||
public static enum StatisticsType {
|
||||
VIEW("view"),
|
||||
@@ -192,9 +193,6 @@ public class SolrLoggerServiceImpl implements SolrLoggerService, InitializingBea
|
||||
log.error("The required 'dbfile' configuration is missing in solr-statistics.cfg!");
|
||||
}
|
||||
locationService = service;
|
||||
|
||||
useProxies = configurationService.getBooleanProperty("useProxies");
|
||||
log.info("useProxies=" + useProxies);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -296,26 +294,7 @@ public class SolrLoggerServiceImpl implements SolrLoggerService, InitializingBea
|
||||
// Save our basic info that we already have
|
||||
|
||||
if (request != null) {
|
||||
String ip = request.getRemoteAddr();
|
||||
|
||||
if (isUseProxies() && request.getHeader("X-Forwarded-For") != null) {
|
||||
/* This header is a comma delimited list */
|
||||
for (String xfip : request.getHeader("X-Forwarded-For").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 (!request.getHeader("X-Forwarded-For").contains(ip)) {
|
||||
ip = xfip.trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isUseProxies() && request.getHeader("X-Forwarded-For") != null) {
|
||||
log.warn(
|
||||
"X-Forwarded-For header detected but useProxies is not enabled. If your dspace is behind a proxy " +
|
||||
"set it to true");
|
||||
}
|
||||
|
||||
String ip = clientInfoService.getClientIp(request);
|
||||
doc1.addField("ip", ip);
|
||||
|
||||
//Also store the referrer
|
||||
@@ -391,23 +370,7 @@ public class SolrLoggerServiceImpl implements SolrLoggerService, InitializingBea
|
||||
SolrInputDocument doc1 = new SolrInputDocument();
|
||||
// Save our basic info that we already have
|
||||
|
||||
if (!isUseProxies() && xforwardedfor != null) {
|
||||
log.warn(
|
||||
"X-Forwarded-For header detected but useProxies is not enabled. If your dspace is behind a proxy set " +
|
||||
"it to true");
|
||||
}
|
||||
if (isUseProxies() && xforwardedfor != null) {
|
||||
/* This header is a comma delimited list */
|
||||
for (String xfip : xforwardedfor.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 (!xforwardedfor.contains(ip)) {
|
||||
ip = xfip.trim();
|
||||
}
|
||||
}
|
||||
|
||||
ip = clientInfoService.getClientIp(ip, xforwardedfor);
|
||||
doc1.addField("ip", ip);
|
||||
|
||||
try {
|
||||
@@ -451,7 +414,6 @@ public class SolrLoggerServiceImpl implements SolrLoggerService, InitializingBea
|
||||
log.error("Unable to get location of request: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dspaceObject != null) {
|
||||
doc1.addField("id", dspaceObject.getID());
|
||||
@@ -604,7 +566,7 @@ public class SolrLoggerServiceImpl implements SolrLoggerService, InitializingBea
|
||||
|
||||
@Override
|
||||
public boolean isUseProxies() {
|
||||
return useProxies;
|
||||
return clientInfoService.isUseProxiesEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -21,6 +21,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.configuration.ConversionException;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.dspace.service.ClientInfoService;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -40,8 +41,6 @@ public class SpiderDetectorServiceImpl implements SpiderDetectorService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SpiderDetectorServiceImpl.class);
|
||||
|
||||
private Boolean useProxies;
|
||||
|
||||
private Boolean useCaseInsensitiveMatching;
|
||||
|
||||
private final List<Pattern> agents
|
||||
@@ -51,6 +50,7 @@ public class SpiderDetectorServiceImpl implements SpiderDetectorService {
|
||||
= Collections.synchronizedList(new ArrayList<Pattern>());
|
||||
|
||||
private ConfigurationService configurationService;
|
||||
private ClientInfoService clientInfoService;
|
||||
|
||||
/**
|
||||
* Sparse HashTable structure to hold IP address ranges.
|
||||
@@ -58,8 +58,9 @@ public class SpiderDetectorServiceImpl implements SpiderDetectorService {
|
||||
private IPTable table = null;
|
||||
|
||||
@Autowired(required = true)
|
||||
public SpiderDetectorServiceImpl(ConfigurationService configurationService) {
|
||||
public SpiderDetectorServiceImpl(ConfigurationService configurationService, ClientInfoService clientInfoService) {
|
||||
this.configurationService = configurationService;
|
||||
this.clientInfoService = clientInfoService;
|
||||
}
|
||||
|
||||
public IPTable getTable() {
|
||||
@@ -104,7 +105,7 @@ public class SpiderDetectorServiceImpl implements SpiderDetectorService {
|
||||
}
|
||||
|
||||
// No. See if any IP addresses match
|
||||
if (isUseProxies() && proxyIPs != null) {
|
||||
if (clientInfoService.isUseProxiesEnabled() && proxyIPs != null) {
|
||||
/* This header is a comma delimited list */
|
||||
for (String xfip : proxyIPs.split(",")) {
|
||||
if (isSpider(xfip)) {
|
||||
@@ -306,12 +307,4 @@ public class SpiderDetectorServiceImpl implements SpiderDetectorService {
|
||||
return useCaseInsensitiveMatching;
|
||||
}
|
||||
|
||||
private boolean isUseProxies() {
|
||||
if (useProxies == null) {
|
||||
useProxies = configurationService.getBooleanProperty("useProxies");
|
||||
}
|
||||
|
||||
return useProxies;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -38,7 +38,6 @@ public class MockSolrLoggerServiceImpl
|
||||
File locationDb = new File(locationDbPath);
|
||||
locationDb.createNewFile();
|
||||
locationService = new DatabaseReader.Builder(locationDb).build();
|
||||
useProxies = configurationService.getBooleanProperty("useProxies");
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -13,6 +13,8 @@ import static org.junit.Assert.assertTrue;
|
||||
import mockit.Mock;
|
||||
import mockit.MockUp;
|
||||
import org.dspace.AbstractDSpaceTest;
|
||||
import org.dspace.core.factory.CoreServiceFactory;
|
||||
import org.dspace.service.ClientInfoService;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
import org.dspace.statistics.SolrLoggerServiceImpl;
|
||||
@@ -32,14 +34,15 @@ public class SpiderDetectorServiceImplTest extends AbstractDSpaceTest {
|
||||
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
private ClientInfoService clientInfoService;
|
||||
|
||||
private SpiderDetectorService spiderDetectorService;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
spiderDetectorService = new SpiderDetectorServiceImpl(configurationService);
|
||||
|
||||
clientInfoService = CoreServiceFactory.getInstance().getClientInfoService();
|
||||
spiderDetectorService = new SpiderDetectorServiceImpl(configurationService, clientInfoService);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -60,7 +63,7 @@ public class SpiderDetectorServiceImplTest extends AbstractDSpaceTest {
|
||||
@Test
|
||||
public void testCaseInsensitiveMatching() throws Exception {
|
||||
configurationService.setProperty("usage-statistics.bots.case-insensitive", true);
|
||||
spiderDetectorService = new SpiderDetectorServiceImpl(configurationService);
|
||||
spiderDetectorService = new SpiderDetectorServiceImpl(configurationService, clientInfoService);
|
||||
|
||||
DummyHttpServletRequest req = new DummyHttpServletRequest();
|
||||
req.setAddress(NOT_A_BOT_ADDRESS); // avoid surprises
|
||||
@@ -265,7 +268,7 @@ public class SpiderDetectorServiceImplTest extends AbstractDSpaceTest {
|
||||
public void testBothLowerAndUpperCaseGetMatched() {
|
||||
|
||||
configurationService.setProperty("usage-statistics.bots.case-insensitive", true);
|
||||
spiderDetectorService = new SpiderDetectorServiceImpl(configurationService);
|
||||
spiderDetectorService = new SpiderDetectorServiceImpl(configurationService, clientInfoService);
|
||||
|
||||
DummyHttpServletRequest req = new DummyHttpServletRequest();
|
||||
req.setAddress(NOT_A_BOT_ADDRESS); // avoid surprises
|
||||
@@ -297,7 +300,7 @@ public class SpiderDetectorServiceImplTest extends AbstractDSpaceTest {
|
||||
@Test
|
||||
public void testNonBooleanConfig() {
|
||||
configurationService.setProperty("usage-statistics.bots.case-insensitive", "RandomNonBooleanString");
|
||||
spiderDetectorService = new SpiderDetectorServiceImpl(configurationService);
|
||||
spiderDetectorService = new SpiderDetectorServiceImpl(configurationService, clientInfoService);
|
||||
|
||||
DummyHttpServletRequest req = new DummyHttpServletRequest();
|
||||
req.setAddress(NOT_A_BOT_ADDRESS); // avoid surprises
|
||||
|
@@ -38,6 +38,7 @@ import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.Group;
|
||||
import org.dspace.eperson.service.EPersonService;
|
||||
import org.dspace.service.ClientInfoService;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -71,6 +72,9 @@ public class JWTTokenHandler implements InitializingBean {
|
||||
@Autowired
|
||||
private EPersonService ePersonService;
|
||||
|
||||
@Autowired
|
||||
private ClientInfoService clientInfoService;
|
||||
|
||||
private String jwtKey;
|
||||
private long expirationTime;
|
||||
private boolean includeIP;
|
||||
@@ -276,11 +280,7 @@ public class JWTTokenHandler implements InitializingBean {
|
||||
}
|
||||
|
||||
private String getIpAddress(HttpServletRequest request) {
|
||||
String ipAddress = request.getHeader("X-FORWARDED-FOR");
|
||||
if (ipAddress == null) {
|
||||
ipAddress = request.getRemoteAddr();
|
||||
}
|
||||
return ipAddress;
|
||||
return clientInfoService.getClientIp(request);
|
||||
}
|
||||
|
||||
private EPerson updateSessionSalt(final Context context, final Date previousLoginDate) throws SQLException {
|
||||
|
@@ -23,6 +23,7 @@ import com.nimbusds.jwt.SignedJWT;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.service.EPersonService;
|
||||
import org.dspace.service.ClientInfoService;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -62,6 +63,9 @@ public class JWTTokenHandlerTest {
|
||||
@Mock
|
||||
private EPersonClaimProvider ePersonClaimProvider;
|
||||
|
||||
@Mock
|
||||
private ClientInfoService clientInfoService;
|
||||
|
||||
@Spy
|
||||
private List<JWTClaimProvider> jwtClaimProviders = new ArrayList<>();
|
||||
|
||||
@@ -71,6 +75,7 @@ public class JWTTokenHandlerTest {
|
||||
when(ePerson.getSessionSalt()).thenReturn("01234567890123456789012345678901");
|
||||
when(ePerson.getLastActive()).thenReturn(new Date());
|
||||
when(context.getCurrentUser()).thenReturn(ePerson);
|
||||
when(clientInfoService.getClientIp(any())).thenReturn("123.123.123.123");
|
||||
when(ePersonClaimProvider.getKey()).thenReturn("eid");
|
||||
when(ePersonClaimProvider.getValue(any(), Mockito.any(HttpServletRequest.class))).thenReturn("epersonID");
|
||||
jwtClaimProviders.add(ePersonClaimProvider);
|
||||
|
@@ -42,7 +42,6 @@ public class MockSolrLoggerServiceImpl
|
||||
File locationDb = new File(locationDbPath);
|
||||
locationDb.createNewFile();
|
||||
locationService = new DatabaseReader.Builder(locationDb).build();
|
||||
useProxies = configurationService.getBooleanProperty("useProxies");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -326,7 +326,19 @@ http.proxy.port =
|
||||
|
||||
# If enabled, the logging and the Solr statistics system will look for
|
||||
# an X-Forwarded-For header. If it finds it, it will use this for the user IP address
|
||||
useProxies = false
|
||||
# Note that server-side rendered Angular UI requests always present the X-Forwarded-For header
|
||||
# with the original client IP address.
|
||||
useProxies = true
|
||||
|
||||
# If "useProxies" is enabled, the authentication and statistics logging code will read the X-Forwarded-For header in
|
||||
# order to determine the correct client IP address. But they will only use that header value when the request is coming
|
||||
# from a trusted proxy server location (e.g. HTTPD on localhost). Leave this property empty to trust X-Forwarded-For
|
||||
# values of all requests. You can specify a range by only listing the first three ip-address blocks, e.g. 128.177.243
|
||||
# You can list multiple IP addresses or ranges by comma-separating them.
|
||||
# If you are running REST & UI on different servers, you should add the UI servers (range) as a proxy.
|
||||
# For example : proxies.trusted.ipranges = 127.0.0.1, 192.168.2
|
||||
# This is necessary because Angular Universal will also behave as a proxy server.
|
||||
proxies.trusted.ipranges = 127.0.0.1
|
||||
|
||||
#### Media Filter / Format Filter plugins (through PluginService) ####
|
||||
# Media/Format Filters help to full-text index content or
|
||||
|
@@ -93,6 +93,7 @@
|
||||
<bean class="org.dspace.license.CreativeCommonsServiceImpl"/>
|
||||
|
||||
<bean id="spiderDetectorService" class="org.dspace.statistics.util.SpiderDetectorServiceImpl"/>
|
||||
<bean id="clientInfoService" class="org.dspace.service.impl.ClientInfoServiceImpl"/>
|
||||
|
||||
<bean class="org.dspace.versioning.VersionHistoryServiceImpl"/>
|
||||
|
||||
|
Reference in New Issue
Block a user