在Servlet中为HTTP和HTTPS请求获取完整的URL和查询字符串

时间:2020-12-31 11:23:58

I am writing a code which task is to retrieve a requested URL or full path. I've written this code:

我正在编写一个代码,任务是检索请求的URL或完整路径。我写的这段代码:

HttpServletRequest request;//obtained from other functions
String uri = request.getRequestURI();
if (request.getQueryString() != null)
    uri += "?" + request.getQueryString();

So, when I browse http://google.com?q=abc it is OK (correct). But there is problem when I browse https://google.com. The value of uri is http://google.com:443google.com:443, So the program doesn't only when HTTPS is used.

那么,当我浏览http://google.com?q=abc没问题(正确)。但当我浏览https://google.com时,就有问题了。uri的值是http://google.com:443google.com:443,所以这个程序不仅在使用HTTPS时才会使用。

And the output is same for request.getRequestURL().toString().

对于request.getRequestURL(). tostring(),输出是相同的。

What is the solution?

解决方案是什么?

3 个解决方案

#1


128  

By design, getRequestURL() gives you the full URL, missing only the query string.

按照设计,getRequestURL()提供完整的URL,只缺少查询字符串。

In HttpServletRequest, you can get individual parts of the URI using the methods below:

在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"
  • .getScheme() will give you "https" if it was a https://domain request.
  • 如果是https://domain请求,. getscheme()会给你“https”。
  • .getServerName() gives domain on http(s)://domain.
  • . getservername()给出http上的域://域。
  • .getServerPort() will give you the port.
  • getserverport()将为您提供端口。

Use the snippet below:

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() : "");

This snippet above will get the full URI, hiding the port if the default one was used, and not adding the "?" and the query string if the latter was not provided.

上面的代码片段将获得完整的URI,如果使用了缺省端口,则隐藏端口,如果没有提供后者,则不添加“?”和查询字符串。


Proxied requests

Note, that if your request passes through a proxy, you need to look at the X-Forwarded-Proto header since the scheme might be altered:

注意,如果您的请求通过代理,那么您需要查看x -转发- proto头,因为该方案可能会被修改:

request.getHeader("X-Forwarded-Proto")

Also, a common header is X-Forwarded-For, which show the original request IP instead of the proxys IP.

另外,一个通用的header是x - forward - for,它显示原始的请求IP而不是代理IP。

request.getHeader("X-Forwarded-For")

If you are responsible for the configuration of the proxy/load balancer yourself, you need to ensure that these headers are set upon forwarding.

如果您自己负责代理/负载平衡器的配置,则需要确保这些头是在转发时设置的。

#2


7  

Simply Use:

String Uri = request.getRequestURL()+"?"+request.getQueryString();

#3


1  

The fact that a HTTPS request becomes HTTP when you tried to construct the URL on server side indicates that you might have a proxy/load balancer (nginx, pound, etc.) offloading SSL encryption in front and forward to your back end service in plain HTTP.

当您尝试在服务器端构造URL时,HTTPS请求变成了HTTP,这一事实表明您可能有一个代理/负载均衡器(nginx、pound等)在前面卸载SSL加密,然后以普通的HTTP转发给后端服务。

If that's case, check,

如果这是情况下,检查,

  1. whether your proxy has been set up to forward headers correctly (Host, X-forwarded-proto, X-forwarded-for, etc).
  2. 是否正确地将代理设置为转发头(主机、x -forward -proto、x -forward -for等)。
  3. whether your service container (E.g. Tomcat) is set up to recognize the proxy in front. For example, Tomcat requires adding secure="true" scheme="https" proxyPort="443" attributes to its Connector
  4. 是否设置了服务容器(例如Tomcat)以识别前面的代理。例如,Tomcat需要向其连接器添加secure="true" scheme="https" proxyPort="443"属性
  5. whether your code, or service container is processing the headers correctly. For example, Tomcat automatically replaces scheme, remoteAddr, etc. values when you add RemoteIpValve to its Engine. (see Configuration guide, JavaDoc) so you don't have to process these headers in your code manually.
  6. 无论您的代码或服务容器是否正确地处理报头。例如,在向其引擎添加RemoteIpValve时,Tomcat会自动替换scheme、remoteAddr等值。(请参阅Configuration guide, JavaDoc),这样您就不必在代码中手工处理这些标头。

Incorrect proxy header values could result in incorrect output when request.getRequestURI() or request.getRequestURL() attempts to construct the originating URL.

当request.getRequestURI()或request.getRequestURL()试图构造原始URL时,不正确的代理头值可能导致不正确的输出。

#1


128  

By design, getRequestURL() gives you the full URL, missing only the query string.

按照设计,getRequestURL()提供完整的URL,只缺少查询字符串。

In HttpServletRequest, you can get individual parts of the URI using the methods below:

在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"
  • .getScheme() will give you "https" if it was a https://domain request.
  • 如果是https://domain请求,. getscheme()会给你“https”。
  • .getServerName() gives domain on http(s)://domain.
  • . getservername()给出http上的域://域。
  • .getServerPort() will give you the port.
  • getserverport()将为您提供端口。

Use the snippet below:

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() : "");

This snippet above will get the full URI, hiding the port if the default one was used, and not adding the "?" and the query string if the latter was not provided.

上面的代码片段将获得完整的URI,如果使用了缺省端口,则隐藏端口,如果没有提供后者,则不添加“?”和查询字符串。


Proxied requests

Note, that if your request passes through a proxy, you need to look at the X-Forwarded-Proto header since the scheme might be altered:

注意,如果您的请求通过代理,那么您需要查看x -转发- proto头,因为该方案可能会被修改:

request.getHeader("X-Forwarded-Proto")

Also, a common header is X-Forwarded-For, which show the original request IP instead of the proxys IP.

另外,一个通用的header是x - forward - for,它显示原始的请求IP而不是代理IP。

request.getHeader("X-Forwarded-For")

If you are responsible for the configuration of the proxy/load balancer yourself, you need to ensure that these headers are set upon forwarding.

如果您自己负责代理/负载平衡器的配置,则需要确保这些头是在转发时设置的。

#2


7  

Simply Use:

String Uri = request.getRequestURL()+"?"+request.getQueryString();

#3


1  

The fact that a HTTPS request becomes HTTP when you tried to construct the URL on server side indicates that you might have a proxy/load balancer (nginx, pound, etc.) offloading SSL encryption in front and forward to your back end service in plain HTTP.

当您尝试在服务器端构造URL时,HTTPS请求变成了HTTP,这一事实表明您可能有一个代理/负载均衡器(nginx、pound等)在前面卸载SSL加密,然后以普通的HTTP转发给后端服务。

If that's case, check,

如果这是情况下,检查,

  1. whether your proxy has been set up to forward headers correctly (Host, X-forwarded-proto, X-forwarded-for, etc).
  2. 是否正确地将代理设置为转发头(主机、x -forward -proto、x -forward -for等)。
  3. whether your service container (E.g. Tomcat) is set up to recognize the proxy in front. For example, Tomcat requires adding secure="true" scheme="https" proxyPort="443" attributes to its Connector
  4. 是否设置了服务容器(例如Tomcat)以识别前面的代理。例如,Tomcat需要向其连接器添加secure="true" scheme="https" proxyPort="443"属性
  5. whether your code, or service container is processing the headers correctly. For example, Tomcat automatically replaces scheme, remoteAddr, etc. values when you add RemoteIpValve to its Engine. (see Configuration guide, JavaDoc) so you don't have to process these headers in your code manually.
  6. 无论您的代码或服务容器是否正确地处理报头。例如,在向其引擎添加RemoteIpValve时,Tomcat会自动替换scheme、remoteAddr等值。(请参阅Configuration guide, JavaDoc),这样您就不必在代码中手工处理这些标头。

Incorrect proxy header values could result in incorrect output when request.getRequestURI() or request.getRequestURL() attempts to construct the originating URL.

当request.getRequestURI()或request.getRequestURL()试图构造原始URL时,不正确的代理头值可能导致不正确的输出。