You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何防范HttpServletRequest的getServerName与getRequestURL方法遭伪造攻击

替代HttpServletRequest获取可信服务器名/域名的方案

除了白名单校验,还有以下几种可靠的方案来获取可信的服务器名或域名:

  • 直接读取服务器配置的固定域名
    既然客户端传入的Host头不可信,最直接的方式是使用服务器/应用自身配置的可信域名。比如在Spring Boot中,可以通过配置文件定义app.trusted-domain=example.com,然后在代码中用@Value("${app.trusted-domain}")注入使用;如果是Tomcat等容器,可以读取server.xml中<Host>节点的name属性值。这种方式完全不依赖客户端请求,避免了伪造风险。

  • 利用反向代理传递可信头部
    如果请求经过Nginx、Apache等反向代理,可以让代理添加一个自定义的、仅由代理设置的头部(比如X-Trusted-ServerName),将代理配置的server_name传递给后端应用。关键是要在代理层拦截客户端传入的同名头部,防止伪造:

    # Nginx配置示例
    proxy_set_header X-Trusted-ServerName ""; # 先清空客户端传入的头部
    proxy_set_header X-Trusted-ServerName $server_name; # 再设置可信值
    

    后端应用直接读取这个头部的值即可,因为只有代理能设置它,客户端无法篡改。

  • 从HTTPS SSL证书解析域名
    对于HTTPS请求,服务器的SSL证书中包含了绑定的域名信息(CN字段或SAN扩展),可以通过请求的SSL会话获取证书并解析:

    SSLSession sslSession = ((HttpServletRequest) request).getSession().getSslSession();
    if (sslSession != null) {
        try {
            X509Certificate cert = (X509Certificate) sslSession.getPeerCertificates()[0];
            // 解析证书主题DN中的CN字段
            String subjectDn = cert.getSubjectDN().getName();
            String domain = subjectDn.split("CN=")[1].split(",")[0];
        } catch (SSLPeerUnverifiedException e) {
            // 处理证书验证失败的情况
        }
    }
    

    证书是服务器预先配置的,客户端无法修改,因此解析出的域名是可信的。

  • 基于请求真实IP映射域名
    如果服务器的IP与域名是固定绑定的,可以维护一个IP到域名的映射表。先获取请求的真实IP(注意要从可信反向代理的X-Forwarded-For头部获取,避免客户端伪造IP),再通过映射表找到对应的域名:

    String realIp = request.getHeader("X-Forwarded-For");
    if (realIp == null || realIp.isEmpty()) {
        realIp = request.getRemoteAddr();
    }
    // 假设ipDomainMap是预定义的Map<String, String>
    String trustedDomain = ipDomainMap.get(realIp);
    

    这个方案适合IP固定的内部服务或专属部署场景。

内容的提问来源于stack exchange,提问作者shawn.123

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 11:45:57