springboot请求头x-forwarded-proto设置https,request.getScheme为http问题排查

springboot请求头x-forwarded-proto设置https,request.getScheme为http问题排查

记录一次项目中网关代理过来的请求头中x-forwarded-proto为https,但是后台request.getScheme()为http的排查过程

idea全局搜索x-forwarded-proto关键字(RemoteIpValue.class)

	private String protocolHeader = "X-Forwarded-Proto";

定位到org.apache.catalina.valves.RemoteIpValve这个类中处理该请求头,具体方法为invoke(Request request, Response response)

跟踪invoke代码

public void invoke(Request request, Response response) throws IOException, ServletException {
        final String originalRemoteAddr = request.getRemoteAddr();
		/*
		....
        */
        // 此处判断客户端网络是否在Tomcat内部正则中
        boolean isInternal = internalProxies != null &&
                internalProxies.matcher(originalRemoteAddr).matches();

        if (isInternal || (trustedProxies != null &&
                trustedProxies.matcher(originalRemoteAddr).matches())) {
                /*
                ...
                */
                if (protocolHeader != null) {
                String protocolHeaderValue = request.getHeader(protocolHeader);
                if (protocolHeaderValue == null) {
                    // Don't modify the secure, scheme and serverPort attributes
                    // of the request
                // 该段代码判断protocolHeaderValue是否为https
                } else if (isForwardedProtoHeaderValueSecure(protocolHeaderValue)) {
                    request.setSecure(true);
                    // 此处设置request中的scheme值
                    request.getCoyoteRequest().scheme().setString("https");
                    setPorts(request, httpsServerPort);
                } else {
                    request.setSecure(false);
                    request.getCoyoteRequest().scheme().setString("http");
                    setPorts(request, httpServerPort);
                }
            }
        }
}

此处判断最终定位为isInternal为false,导致tomcat未将x-forwarded-proto值塞到scheme中,接下来我们继续跟踪
boolean isInternal = internalProxies != null && internalProxies.matcher(originalRemoteAddr).matches();
发现internalProxies会对客户端IP进行正则校验,满足正则才会设置scheme属性,继续跟踪internalProxies

    private Pattern internalProxies = Pattern.compile(
            "10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" +
            "192\\.168\\.\\d{1,3}\\.\\d{1,3}|" +
            "169\\.254\\.\\d{1,3}\\.\\d{1,3}|" +
            "127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" +
            "172\\.1[6-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" +
            "172\\.2[0-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" +
            "172\\.3[0-1]{1}\\.\\d{1,3}\\.\\d{1,3}|" +
            "0:0:0:0:0:0:0:1|::1");

这时发现我们网关的ip地址为100.xxx.xx.xxx,并未匹配上该正则,基于网络IP无法修改,我们通过修改tomcat配置来修复,springboot该配置如下:

server.tomcat.internal-proxies=
100\.\d{1,3}\.\d{1,3}\.\d{1,3}|10\.\d{1,3}\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|169\.254\.\d{1,3}\.\d{1,3}|127\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.1[6-9]{1}\.\d{1,3}\.\d{1,3}|172\.2[0-9]{1}\.\d{1,3}\.\d{1,3}|172\.3[0-1]{1}\.\d{1,3}\.\d{1,3}|0:0:0:0:0:0:0:1|::1

在配置中新增100\.\d{1,3}\.\d{1,3}\.\d{1,3}正则,重启服务,解决问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值