mirror of https://github.com/halo-dev/halo
Check X-Real-IP header when obtaining client IP (#4139)
#### What type of PR is this? /kind bug /area core /milestone 2.7.x #### What this PR does / why we need it: In some special situations, Halo can not obtain client IP address from request headers and socket address is unresolved, so that `java.lang.NullPointerException: Cannot invoke "java.net.InetAddress.getHostAddress()" because the return value of "java.net.InetSocketAddress.getAddress()" is null` will happen. This PR will resolve the problem by checking `X-Real-IP` header and checking if remote address is unresolved. #### Which issue(s) this PR fixes: Fixes https://github.com/halo-dev/halo/issues/4134 #### Does this PR introduce a user-facing change? ```release-note None ```pull/4069/head^2
parent
25103b9ff8
commit
4aec1ba8f6
|
@ -2,6 +2,7 @@ package run.halo.app.infra.utils;
|
|||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
|
||||
/**
|
||||
|
@ -14,6 +15,7 @@ public class IpAddressUtils {
|
|||
|
||||
private static final String[] IP_HEADER_NAMES = {
|
||||
"X-Forwarded-For",
|
||||
"X-Real-IP",
|
||||
"Proxy-Client-IP",
|
||||
"WL-Proxy-Client-IP",
|
||||
"CF-Connecting-IP",
|
||||
|
@ -36,17 +38,18 @@ public class IpAddressUtils {
|
|||
public static String getClientIp(ServerHttpRequest request) {
|
||||
for (String header : IP_HEADER_NAMES) {
|
||||
String ipList = request.getHeaders().getFirst(header);
|
||||
if (ipList != null && ipList.length() != 0 && !"unknown".equalsIgnoreCase(ipList)) {
|
||||
if (StringUtils.hasText(ipList) && !UNKNOWN.equalsIgnoreCase(ipList)) {
|
||||
String[] ips = ipList.trim().split("[,;]");
|
||||
for (String ip : ips) {
|
||||
if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
|
||||
if (StringUtils.hasText(ip) && !UNKNOWN.equalsIgnoreCase(ip)) {
|
||||
return ip;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var remoteAddress = request.getRemoteAddress();
|
||||
return remoteAddress == null ? UNKNOWN : remoteAddress.getAddress().getHostAddress();
|
||||
return remoteAddress == null || remoteAddress.isUnresolved()
|
||||
? UNKNOWN : remoteAddress.getAddress().getHostAddress();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package run.halo.app.infra.utils;
|
|||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
||||
|
@ -19,12 +20,31 @@ class IpAddressUtilsTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testGetUnknownIPAddress() {
|
||||
void testGetIPAddressFromXRealIpHeader() {
|
||||
var request = MockServerHttpRequest.get("/")
|
||||
.header("X-Real-IP", "127.0.0.1")
|
||||
.build();
|
||||
var expected = "127.0.0.1";
|
||||
var actual = IpAddressUtils.getClientIp(request);
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetUnknownIPAddressWhenRemoteAddressIsNull() {
|
||||
var request = MockServerHttpRequest.get("/").build();
|
||||
var actual = IpAddressUtils.getClientIp(request);
|
||||
assertEquals(IpAddressUtils.UNKNOWN, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetUnknownIPAddressWhenRemoteAddressIsUnresolved() {
|
||||
var request = MockServerHttpRequest.get("/")
|
||||
.remoteAddress(InetSocketAddress.createUnresolved("localhost", 8090))
|
||||
.build();
|
||||
var actual = IpAddressUtils.getClientIp(request);
|
||||
assertEquals(IpAddressUtils.UNKNOWN, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetIPAddressWithMultipleHeaders() {
|
||||
var headers = new HttpHeaders();
|
||||
|
|
Loading…
Reference in New Issue