24
24
import java .util .Map ;
25
25
import java .util .Set ;
26
26
import java .util .function .Supplier ;
27
+ import java .util .regex .Pattern ;
27
28
28
29
import javax .servlet .FilterChain ;
29
30
import javax .servlet .ServletException ;
32
33
import javax .servlet .http .HttpServletResponse ;
33
34
import javax .servlet .http .HttpServletResponseWrapper ;
34
35
36
+ import org .springframework .http .HttpHeaders ;
35
37
import org .springframework .http .HttpRequest ;
36
38
import org .springframework .http .HttpStatus ;
37
39
import org .springframework .http .server .ServletServerHttpRequest ;
67
69
public class ForwardedHeaderFilter extends OncePerRequestFilter {
68
70
69
71
private static final Set <String > FORWARDED_HEADER_NAMES =
70
- Collections .newSetFromMap (new LinkedCaseInsensitiveMap <>(6 , Locale .ENGLISH ));
72
+ Collections .newSetFromMap (new LinkedCaseInsensitiveMap <>(10 , Locale .ENGLISH ));
71
73
72
74
static {
73
75
FORWARDED_HEADER_NAMES .add ("Forwarded" );
@@ -76,6 +78,7 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter {
76
78
FORWARDED_HEADER_NAMES .add ("X-Forwarded-Proto" );
77
79
FORWARDED_HEADER_NAMES .add ("X-Forwarded-Prefix" );
78
80
FORWARDED_HEADER_NAMES .add ("X-Forwarded-Ssl" );
81
+ FORWARDED_HEADER_NAMES .add ("X-Forwarded-For" );
79
82
}
80
83
81
84
@@ -217,6 +220,10 @@ public Enumeration<String> getHeaderNames() {
217
220
*/
218
221
private static class ForwardedHeaderExtractingRequest extends ForwardedHeaderRemovingRequest {
219
222
223
+ private static final String X_FORWARDED_FOR_HEADER = "X-Forwarded-For" ;
224
+ private static final String FORWARDED_HEADER = "Forwarded" ;
225
+ private static final Pattern FORWARDED_FOR_PATTERN = Pattern .compile ("(?i:^[^,]*for=.+)" );
226
+
220
227
@ Nullable
221
228
private final String scheme ;
222
229
@@ -227,6 +234,14 @@ private static class ForwardedHeaderExtractingRequest extends ForwardedHeaderRem
227
234
228
235
private final int port ;
229
236
237
+ @ Nullable
238
+ private final String remoteHost ;
239
+
240
+ @ Nullable
241
+ private final String remoteAddr ;
242
+
243
+ private final int remotePort ;
244
+
230
245
private final ForwardedPrefixExtractor forwardedPrefixExtractor ;
231
246
232
247
@@ -242,6 +257,25 @@ private static class ForwardedHeaderExtractingRequest extends ForwardedHeaderRem
242
257
this .host = uriComponents .getHost ();
243
258
this .port = (port == -1 ? (this .secure ? 443 : 80 ) : port );
244
259
260
+ HttpHeaders headers = httpRequest .getHeaders ();
261
+ boolean hasForwardedFor = StringUtils .hasText (headers .getFirst (X_FORWARDED_FOR_HEADER )) ||
262
+ (StringUtils .hasText (headers .getFirst (FORWARDED_HEADER )) &&
263
+ FORWARDED_FOR_PATTERN .matcher (headers .getFirst (FORWARDED_HEADER )).matches ());
264
+ if (hasForwardedFor ) {
265
+ UriComponents remoteUriComponents = UriComponentsBuilder .newInstance ()
266
+ .host (request .getRemoteHost ())
267
+ .port (request .getRemotePort ())
268
+ .adaptFromForwardedForHeader (headers )
269
+ .build ();
270
+ this .remoteHost = remoteUriComponents .getHost ();
271
+ this .remoteAddr = this .remoteHost ;
272
+ this .remotePort = remoteUriComponents .getPort ();
273
+ } else {
274
+ this .remoteHost = request .getRemoteHost ();
275
+ this .remoteAddr = request .getRemoteAddr ();
276
+ this .remotePort = request .getRemotePort ();
277
+ }
278
+
245
279
String baseUrl = this .scheme + "://" + this .host + (port == -1 ? "" : ":" + port );
246
280
Supplier <HttpServletRequest > delegateRequest = () -> (HttpServletRequest ) getRequest ();
247
281
this .forwardedPrefixExtractor = new ForwardedPrefixExtractor (delegateRequest , pathHelper , baseUrl );
@@ -284,6 +318,23 @@ public String getRequestURI() {
284
318
public StringBuffer getRequestURL () {
285
319
return this .forwardedPrefixExtractor .getRequestUrl ();
286
320
}
321
+
322
+ @ Override
323
+ @ Nullable
324
+ public String getRemoteHost () {
325
+ return this .remoteHost ;
326
+ }
327
+
328
+ @ Override
329
+ @ Nullable
330
+ public String getRemoteAddr () {
331
+ return this .remoteAddr ;
332
+ }
333
+
334
+ @ Override
335
+ public int getRemotePort () {
336
+ return remotePort ;
337
+ }
287
338
}
288
339
289
340
0 commit comments