Move HeaderUtils#getMostRecentyProxy to RemoteAddressFilter
This commit is contained in:
parent
fcae100df1
commit
0965ab8063
|
@ -5,17 +5,20 @@
|
||||||
|
|
||||||
package org.whispersystems.textsecuregcm.filters;
|
package org.whispersystems.textsecuregcm.filters;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Optional;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import javax.servlet.Filter;
|
import javax.servlet.Filter;
|
||||||
import javax.servlet.FilterChain;
|
import javax.servlet.FilterChain;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
import javax.servlet.ServletResponse;
|
import javax.servlet.ServletResponse;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.textsecuregcm.util.HeaderUtils;
|
|
||||||
import org.whispersystems.textsecuregcm.util.HttpServletRequestUtil;
|
import org.whispersystems.textsecuregcm.util.HttpServletRequestUtil;
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a {@link HttpServletRequest} attribute (that will also be available as a
|
* Sets a {@link HttpServletRequest} attribute (that will also be available as a
|
||||||
|
@ -47,7 +50,7 @@ public class RemoteAddressFilter implements Filter {
|
||||||
remoteAddress = HttpServletRequestUtil.getRemoteAddress(httpServletRequest);
|
remoteAddress = HttpServletRequestUtil.getRemoteAddress(httpServletRequest);
|
||||||
} else {
|
} else {
|
||||||
final String forwardedFor = httpServletRequest.getHeader(com.google.common.net.HttpHeaders.X_FORWARDED_FOR);
|
final String forwardedFor = httpServletRequest.getHeader(com.google.common.net.HttpHeaders.X_FORWARDED_FOR);
|
||||||
remoteAddress = HeaderUtils.getMostRecentProxy(forwardedFor)
|
remoteAddress = getMostRecentProxy(forwardedFor)
|
||||||
.orElseGet(() -> HttpServletRequestUtil.getRemoteAddress(httpServletRequest));
|
.orElseGet(() -> HttpServletRequestUtil.getRemoteAddress(httpServletRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,4 +62,25 @@ public class RemoteAddressFilter implements Filter {
|
||||||
|
|
||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the most recent proxy in a chain described by an {@code X-Forwarded-For} header.
|
||||||
|
*
|
||||||
|
* @param forwardedFor the value of an X-Forwarded-For header
|
||||||
|
* @return the IP address of the most recent proxy in the forwarding chain, or empty if none was found or
|
||||||
|
* {@code forwardedFor} was null
|
||||||
|
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For">X-Forwarded-For - HTTP |
|
||||||
|
* MDN</a>
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
static Optional<String> getMostRecentProxy(@Nullable final String forwardedFor) {
|
||||||
|
return Optional.ofNullable(forwardedFor)
|
||||||
|
.map(ff -> {
|
||||||
|
final int idx = forwardedFor.lastIndexOf(',') + 1;
|
||||||
|
return idx < forwardedFor.length()
|
||||||
|
? forwardedFor.substring(idx).trim()
|
||||||
|
: null;
|
||||||
|
})
|
||||||
|
.filter(StringUtils::isNotBlank);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,6 @@ import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentials;
|
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentials;
|
||||||
|
|
||||||
public final class HeaderUtils {
|
public final class HeaderUtils {
|
||||||
|
@ -47,28 +45,6 @@ public final class HeaderUtils {
|
||||||
return TIMESTAMP_HEADER + ":" + System.currentTimeMillis();
|
return TIMESTAMP_HEADER + ":" + System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the most recent proxy in a chain described by an {@code X-Forwarded-For} header.
|
|
||||||
*
|
|
||||||
* @param forwardedFor the value of an X-Forwarded-For header
|
|
||||||
*
|
|
||||||
* @return the IP address of the most recent proxy in the forwarding chain, or empty if none was found or
|
|
||||||
* {@code forwardedFor} was null
|
|
||||||
*
|
|
||||||
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For">X-Forwarded-For - HTTP | MDN</a>
|
|
||||||
*/
|
|
||||||
@Nonnull
|
|
||||||
public static Optional<String> getMostRecentProxy(@Nullable final String forwardedFor) {
|
|
||||||
return Optional.ofNullable(forwardedFor)
|
|
||||||
.map(ff -> {
|
|
||||||
final int idx = forwardedFor.lastIndexOf(',') + 1;
|
|
||||||
return idx < forwardedFor.length()
|
|
||||||
? forwardedFor.substring(idx).trim()
|
|
||||||
: null;
|
|
||||||
})
|
|
||||||
.filter(StringUtils::isNotBlank);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a Base64-encoded value of the `Authorization` header
|
* Parses a Base64-encoded value of the `Authorization` header
|
||||||
* in the form of `Basic dXNlcm5hbWU6cGFzc3dvcmQ=`.
|
* in the form of `Basic dXNlcm5hbWU6cGFzc3dvcmQ=`.
|
||||||
|
|
|
@ -5,18 +5,24 @@
|
||||||
|
|
||||||
package org.whispersystems.textsecuregcm.filters;
|
package org.whispersystems.textsecuregcm.filters;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import com.google.common.net.HttpHeaders;
|
import com.google.common.net.HttpHeaders;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import javax.servlet.FilterChain;
|
import javax.servlet.FilterChain;
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
import javax.servlet.ServletResponse;
|
import javax.servlet.ServletResponse;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
import org.junit.jupiter.params.provider.CsvSource;
|
import org.junit.jupiter.params.provider.CsvSource;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
class RemoteAddressFilterTest {
|
class RemoteAddressFilterTest {
|
||||||
|
|
||||||
|
@ -57,4 +63,23 @@ class RemoteAddressFilterTest {
|
||||||
verify(filterChain).doFilter(any(ServletRequest.class), any(ServletResponse.class));
|
verify(filterChain).doFilter(any(ServletRequest.class), any(ServletResponse.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("argumentsForGetMostRecentProxy")
|
||||||
|
void getMostRecentProxy(final String forwardedFor, final Optional<String> expectedMostRecentProxy) {
|
||||||
|
assertEquals(expectedMostRecentProxy, RemoteAddressFilter.getMostRecentProxy(forwardedFor));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Stream<Arguments> argumentsForGetMostRecentProxy() {
|
||||||
|
return Stream.of(
|
||||||
|
arguments(null, Optional.empty()),
|
||||||
|
arguments("", Optional.empty()),
|
||||||
|
arguments(" ", Optional.empty()),
|
||||||
|
arguments("203.0.113.195,", Optional.empty()),
|
||||||
|
arguments("203.0.113.195, ", Optional.empty()),
|
||||||
|
arguments("203.0.113.195", Optional.of("203.0.113.195")),
|
||||||
|
arguments("203.0.113.195, 70.41.3.18, 150.172.238.178", Optional.of("150.172.238.178"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2021 Signal Messenger, LLC
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.whispersystems.textsecuregcm.util;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
|
||||||
import org.junit.jupiter.params.provider.Arguments;
|
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
|
||||||
|
|
||||||
class HeaderUtilsTest {
|
|
||||||
|
|
||||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
|
||||||
@ParameterizedTest
|
|
||||||
@MethodSource("argumentsForGetMostRecentProxy")
|
|
||||||
void getMostRecentProxy(final String forwardedFor, final Optional<String> expectedMostRecentProxy) {
|
|
||||||
assertEquals(expectedMostRecentProxy, HeaderUtils.getMostRecentProxy(forwardedFor));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Stream<Arguments> argumentsForGetMostRecentProxy() {
|
|
||||||
return Stream.of(
|
|
||||||
arguments(null, Optional.empty()),
|
|
||||||
arguments("", Optional.empty()),
|
|
||||||
arguments(" ", Optional.empty()),
|
|
||||||
arguments("203.0.113.195,", Optional.empty()),
|
|
||||||
arguments("203.0.113.195, ", Optional.empty()),
|
|
||||||
arguments("203.0.113.195", Optional.of("203.0.113.195")),
|
|
||||||
arguments("203.0.113.195, 70.41.3.18, 150.172.238.178", Optional.of("150.172.238.178"))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue