文章目录
- 基于Spring MVC的客户端真实IP获取方案解析
- 概述
- 核心方法解析
- 代码实现
- 工作流程
- IP获取优先级策略
- IP有效性验证
- 异常处理与日志
- 使用场景
- 注意事项
- 扩展建议
基于Spring MVC的客户端真实IP获取方案解析
概述
在Web应用开发中,准确获取客户端真实IP地址是常见的需求。本文介绍一个基于Spring MVC实现的客户端IP获取方案ClientIpController
,该方案支持多种代理场景下的IP识别,并包含完善的校验机制。
核心方法解析
代码实现
/*** 获取客户端公网IP** @author xdr630*/
@RestController
public class ClientIpController {private static final Logger LOGGER = LoggerFactory.getLogger(KocaClientIpController.class);@GetMapping("/getRemoteIp")@ResponseBodypublic String getClientIp(HttpServletRequest request) {String clientIp = null;try {String xForwardedFor = request.getHeader("X-Forwarded-For");if (xForwardedFor != null && !xForwardedFor.isEmpty() && !"unknown".equalsIgnoreCase(xForwardedFor)) {// X-Forwarded-For:Squid 服务代理,X-Forwarded-For 可能包含多个 IP,取第一个非空的 IPclientIp = xForwardedFor.split(",")[0].trim();}if (clientIp == null || clientIp.isEmpty() || "unknown".equalsIgnoreCase(clientIp)) {// Proxy-Client-IP:apache 服务代理clientIp = request.getHeader("Proxy-Client-IP");}if (clientIp == null || clientIp.isEmpty() || "unknown".equalsIgnoreCase(clientIp)) {// WL-Proxy-Client-IP:weblogic 服务代理clientIp = request.getHeader("WL-Proxy-Client-IP");}if ((clientIp == null || clientIp.isEmpty() || "unknown".equalsIgnoreCase(clientIp))) {// X-Real-IP:nginx服务代理clientIp = request.getHeader("X-Real-IP");}if (clientIp == null || clientIp.isEmpty() || "unknown".equalsIgnoreCase(clientIp)) {clientIp = request.getRemoteAddr();}if (clientIp != null && !clientIp.isEmpty()) {clientIp = clientIp.split(",")[0];}if (!isValidIPv4(clientIp)) {LOGGER.warn("无效的客户端 IP: {}", clientIp);// 在浏览器端显示返回nullclientIp = "null";}} catch (Exception e) {LOGGER.error("获取客户端公网IP失败", e);throw new RuntimeException(e);}return clientIp;}private boolean isValidIPv4(String ip) {String ipv4Regex = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$";return Pattern.compile(ipv4Regex).matcher(ip).matches();}
}
工作流程
-
多级代理支持:依次检查以下请求头
X-Forwarded-For
:处理Squid等代理的逗号分隔IPProxy-Client-IP
:Apache代理WL-Proxy-Client-IP
:WebLogic代理X-Real-IP
:Nginx代理
-
最终回退机制
clientIp = request.getRemoteAddr();
- 结果处理
- 取首个有效IP段
- IPv4格式校验
- 异常IP返回"null"字符串
IP获取优先级策略
优先级 | Header名称 | 代理类型 |
---|---|---|
1 | X-Forwarded-For | 通用代理/Squid |
2 | Proxy-Client-IP | Apache |
3 | WL-Proxy-Client-IP | WebLogic |
4 | X-Real-IP | Nginx |
5 | getRemoteAddr() | 直接连接 |
IP有效性验证
采用正则表达式校验IPv4格式:
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
异常处理与日志
- WARN级别日志:记录无效IP格式
- ERROR级别日志:捕获处理异常
- 异常转换:将检查异常转为RuntimeException
使用场景
- 反向代理架构下的真实IP获取
- 客户端地理位置服务
- 访问频率控制
- 安全审计日志
注意事项
- 代理链中的首个IP可能不可信(需结合安全策略)
- 不支持IPv6地址(需扩展正则校验)
- 生产环境建议添加速率限制
- 重要场景建议结合XFF白名单验证
扩展建议
- 增加IPv6支持
- 添加可信代理IP列表验证
- 集成缓存机制防止滥用
- 补充单元测试覆盖边界情况
该方案提供了可靠的客户端IP获取实现,开发人员应根据实际网络架构调整header的检查顺序,并在安全敏感场景中补充额外的验证逻辑。