在Servlet中为HTTP和HTTPS请求获取完整的URL和查询string
我正在写一个代码,其任务是检索请求的URL或完整path。 我已经写了这个代码:
HttpServletRequest request;//obtained from other functions String uri = request.getRequestURI(); if (request.getQueryString() != null) uri += "?" + request.getQueryString();
所以,当我浏览http://google.com?q=abc
,确定(正确)。 但浏览https://google.com
时出现问题。 uri
的值是http://google.com:443google.com:443
,所以程序不仅在使用HTTPS
时。
并且request.getRequestURL().toString()
的输出是相同的。
解决办法是什么?
通过devise, getRequestURL()
为您提供完整的URL,仅缺less查询string。
在HttpServletRequest
,您可以使用以下方法获取URI的各个部分:
// Example: http://myhost:8080/people?lastname=Fox&age=30 String uri = request.getScheme() + "://" + // "http" + ":// request.getServerName() + // "myhost" ":" + // ":" request.getServerPort() + // "8080" request.getRequestURI() + // "/people" "?" + // "?" request.getQueryString(); // "lastname=Fox&age=30"
- 如果是
https://domain
请求,.getScheme()
会给你"https"
。 -
.getServerName()
在http(s)://domain
上给出http(s)://domain
。 -
.getServerPort()
会给你端口。
使用下面的代码片段:
String uri = request.getScheme() + "://" + request.getServerName() + ("http".equals(request.getScheme()) && request.getServerPort() == 80 || "https".equals(request.getScheme()) && request.getServerPort() == 443 ? "" : ":" + request.getServerPort() ) + request.getRequestURI() + (request.getQueryString() != null ? "?" + request.getQueryString() : "");
上面的代码片段将得到完整的URI,如果使用默认的URI,则隐藏端口,不添加"?"
和查询string,如果没有提供后者。
代理请求
请注意,如果您的请求通过代理,您需要查看X-Forwarded-Proto
头,因为该scheme可能会被更改:
request.getHeader("X-Forwarded-Proto")
另外,一个共同的标题是X-Forwarded-For
,它显示原始请求IP而不是代理IP。
request.getHeader("X-Forwarded-For")
如果您自己负责代理/负载均衡器的configuration,则需要确保在转发时设置这些头。
简单使用:
String Uri = request.getRequestURL()+"?"+request.getQueryString();
当您尝试在服务器端构buildURL时, HTTPS
请求变为HTTP
这一事实表明,您可能有一个代理/负载均衡器( nginx
, pound
等)将SSLencryption前后转移到纯后端服务HTTP
。
如果是这种情况,请检查,
- 不pipe你的代理是否已经被正确
X-forwarded-proto
(Host
,X-forwarded-proto
forwardX-forwarded-proto
,X-forwarded-for
forwardX-forwarded-for
等等)。 - 无论您的服务容器(如
Tomcat
)是否设置为识别前面的代理。 例如,Tomcat
需要向其Connector
添加secure="true" scheme="https" proxyPort="443"
属性 - 无论您的代码或服务容器是否正确处理标题。 例如,当您将
RemoteIpValve
添加到其Engine
时,Tomcat
自动replacescheme
,remoteAddr
RemoteIpValve
。 (请参阅configuration指南 , JavaDoc ),因此您不必在代码中手动处理这些头文件。
当request.getRequestURI()
或request.getRequestURL()
尝试构造原始URL时,错误的代理头值可能会导致错误的输出。