From d6f5e61ec8380aba427b36176e8a38479abd79ed Mon Sep 17 00:00:00 2001 From: Camelia Dumitru <62257307+Camelia-Orcid@users.noreply.github.com> Date: Tue, 5 Nov 2024 19:22:21 +0000 Subject: [PATCH] White list implementation for papi limit (#7126) * Added the white list implementation * kept just 127.0.0.1 as the ip address in the whitelist as default * added the Ip address to the info log for anonymous requests --- .../orcid/api/filters/ApiRateLimitFilter.java | 44 +++++++++++++++++-- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/orcid-pub-web/src/main/java/org/orcid/api/filters/ApiRateLimitFilter.java b/orcid-pub-web/src/main/java/org/orcid/api/filters/ApiRateLimitFilter.java index 2db61a53b1..daa982cae3 100644 --- a/orcid-pub-web/src/main/java/org/orcid/api/filters/ApiRateLimitFilter.java +++ b/orcid-pub-web/src/main/java/org/orcid/api/filters/ApiRateLimitFilter.java @@ -3,7 +3,9 @@ import java.io.IOException; import java.io.PrintWriter; import java.time.LocalDate; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -14,6 +16,7 @@ import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.LocaleUtils; +import org.apache.commons.lang3.StringUtils; import org.orcid.core.manager.ClientDetailsEntityCacheManager; import org.orcid.core.manager.OrcidSecurityManager; import org.orcid.core.manager.TemplateManager; @@ -88,6 +91,9 @@ public class ApiRateLimitFilter extends OncePerRequestFilter { @Value("${org.orcid.persistence.panoply.papiExceededRate.production:false}") private boolean enablePanoplyPapiExceededRateInProduction; + + @Value("${org.orcid.papi.rate.limit.ip.whiteSpaceSeparatedWhiteList:127.0.0.1}") + private String papiWhiteSpaceSeparatedWhiteList; private static final String TOO_MANY_REQUESTS_MSG = "Too Many Requests - You have exceeded the daily allowance of API calls.\\n" + "You can increase your daily quota by registering for and using Public API client credentials " @@ -105,7 +111,7 @@ protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServl if (httpServletRequest.getHeader("Authorization") != null) { tokenValue = httpServletRequest.getHeader("Authorization").replaceAll("Bearer|bearer", "").trim(); } - String ipAddress = httpServletRequest.getRemoteAddr(); + String ipAddress = getClientIpAddress(httpServletRequest); String clientId = null; if (tokenValue != null) { @@ -118,9 +124,11 @@ protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServl boolean isAnonymous = (clientId == null); LocalDate today = LocalDate.now(); - if (isAnonymous) { - LOG.info("ApiRateLimitFilter anonymous request"); - this.rateLimitAnonymousRequest(ipAddress, today, httpServletResponse); + if (isAnonymous ) { + if(!isWhiteListed(ipAddress)) { + LOG.info("ApiRateLimitFilter anonymous request for ip: " + ipAddress); + this.rateLimitAnonymousRequest(ipAddress, today, httpServletResponse); + } } else { LOG.info("ApiRateLimitFilter client request with clientId: " + clientId); @@ -250,5 +258,33 @@ private void setPapiRateExceededItemInPanoply(PanoplyPapiDailyRateExceededItem i }); } + + //gets actual client IP address, using the headers that the proxy server ads + private String getClientIpAddress(HttpServletRequest request) { + String ipAddress = request.getHeader("X-FORWARDED-FOR"); + if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("X-REAL-IP"); + } + if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getRemoteAddr(); + } + if (ipAddress != null && ipAddress.contains(",")) { + ipAddress = ipAddress.split(",")[0].trim(); + } + return ipAddress; + } + + private boolean isWhiteListed(String ipAddress) { + List papiIpWhiteList = null; + if(StringUtils.isNotBlank(papiWhiteSpaceSeparatedWhiteList)) { + papiIpWhiteList = Arrays.asList(papiWhiteSpaceSeparatedWhiteList.split("\\s")); + } + + if(papiIpWhiteList != null) { + return papiIpWhiteList.contains(ipAddress); + + } + return false; + } }