Spring Boot经AWS ALB转发时X-Forwarded-For请求头缺失问题求助
问题场景
部署在AWS Application Load Balancer(ALB)后的Spring Boot应用包含如下/test端点:
@GetMapping(value = "/test", produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody public Object getTestResponse(@RequestHeader("id") String id, @RequestHeader(required = true, value = "x-forwarded-for") String clientIpAddress) throws IOException { // 其他逻辑已省略 }
调用命令:
curl -v -H 'id:12345678' -H 'x-forwarded-for:192.168.0.2' http://example.com/context/services/test
明明已传递X-Forwarded-For请求头,却收到错误:
.w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MissingRequestHeaderException: Required request header 'x-forwarded-for' for method parameter type String is not present
已做配置修改:
- Spring Boot端:在
application.yml添加server: forward-headers-strategy: NATIVE - AWS ALB端:将
X-Forwarded-For属性设为Preserve
但问题依旧,以下是排查和解决步骤:
排查与解决步骤
1. 验证ALB的请求头转发
- 查看CloudWatch的ALB访问日志,确认
X-Forwarded-For头是否被正确转发到后端应用; - 若目标组使用HTTP/2协议,切换为HTTP/1.1测试,部分场景下HTTP/2会导致头转发异常;
- 确认ALB和目标组的
X-Forwarded-For配置为Preserve,该模式会保留客户端发送的头并追加ALB源IP,而非覆盖。
2. 调整Spring Boot的Tomcat信任配置
server.forward-headers-strategy: NATIVE依赖Tomcat的原生处理,但Tomcat默认仅信任特定网段的代理,需添加配置让它信任ALB所在网段:
server: forward-headers-strategy: NATIVE tomcat: remoteip: internal-proxies: 10.0.0.0/8|172.16.0.0/12|192.168.0.0/16 # 替换为你的ALB所在VPC网段 remote-ip-header: X-Forwarded-For
只有让Tomcat信任ALB作为反向代理,才会将X-Forwarded-For头解析并传递到Spring的请求上下文。
3. 处理请求头大小写问题
HTTP头本身不区分大小写,但Spring的@RequestHeader默认区分大小写(取决于容器),可修改注解兼容:
@RequestHeader(required = true, value = "x-forwarded-for", ignoreCase = true)
或直接使用标准大写头名称接收:
@RequestHeader(required = true, value = "X-Forwarded-For")
4. 查看Spring Boot请求日志
开启Spring Web的DEBUG日志,确认请求头是否到达应用:
logging: level: org.springframework.web: DEBUG
通过日志可以看到完整的请求头列表,判断X-Forwarded-For是否被中间件(如WAF、API Gateway)过滤。
5. 绕过ALB直接测试应用
直接访问Spring Boot实例的IP+端口,调用/test端点并传递X-Forwarded-For头:
curl -v -H 'id:12345678' -H 'x-forwarded-for:192.168.0.2' http://[实例IP]:[端口]/context/services/test
如果直接访问正常,说明问题出在ALB或中间层配置;若仍报错,则需检查应用本身的拦截器、过滤器是否过滤了该头。
内容的提问来源于stack exchange,提问作者Karthick Vasudevan

