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