fix(pigx-common-security): 修复内部请求校验可被伪造 IP 绕过的问题

- 改用 request.getRemoteAddr() 获取客户端地址,避免从可自定义的转发头提取 IP
- 仅放行 IPv4 回环地址,未携带内部标记的外部请求交由后续认证鉴权处理

(cherry picked from commit b5e5b837ef3e82c4d8231be0bcbd6641c3de7516)
This commit is contained in:
PIGCLOUD committed 2026-11-03 14:49:33 +08:00
1 parent 3b15ea4235
commit ccdbde5229
1 file changed
+7 -7
@@ -2,13 +2,13 @@ package com.pig4cloud.pigx.common.security.component;
import cn.hutool.core.net.Ipv4Util;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.JakartaServletUtil;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.net.IPv6Utils;
import org.jetbrains.annotations.NotNull;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpStatus;
@@ -39,23 +39,23 @@ public class PigxInnerHeaderRemoveFilter extends OncePerRequestFilter {
*/
@Override
protected void doFilterInternal(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain filterChain) throws ServletException, IOException {
// 获取客户端IP地址
String clientIP = JakartaServletUtil.getClientIP(request);
// 使用容器提供的连接地址,不从调用者可填写的转发头提取 IP。
String clientIP = request.getRemoteAddr();
// 允许 127.0.0.1 请求直接通过
if (Ipv4Util.LOCAL_IP.equals(clientIP)) {
// 兼容 IPv4 回环不解析主机名。
if (StrUtil.equalsAny(clientIP, Ipv4Util.LOCAL_IP)) {
filterChain.doFilter(request, response);
return;
}
String fromHeader = request.getHeader(SecurityConstants.FROM);
// 非 127.0.0.1 请求,没有配置 from header ,直接跳过
// 普通请求不携带内部标记,交给后续认证与权限检查。
if (StrUtil.isBlank(fromHeader)) {
filterChain.doFilter(request, response);
return;
}
// 非 127.0.0.1,配置了 from header ,直接拒绝访问
// 外部连接或经过代理的请求,不允许自行声明为内部调用。
log.warn("请求 IP {},疑似进行系统注入操作,请注意", clientIP);
response.setStatus(HttpStatus.FORBIDDEN.value());
}