Spring MVC“重定向:”前缀总是重定向到http——如何让它留在https上?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3401113/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 04:05:49  来源:igfitidea点击:

Spring MVC "redirect:" prefix always redirects to http -- how do I make it stay on https?

springspring-mvc

提问by super_aardvark

I solved this myself, but I spent so long discovering such a simple solution, I figured it deserved to be documented here.

我自己解决了这个问题,但我花了很长时间才发现这样一个简单的解决方案,我认为它值得在这里记录下来。

I have a typical Spring 3 MVC setup with an InternalResourceViewResolver:

我有一个带有 InternalResourceViewResolver 的典型 Spring 3 MVC 设置:

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
  <property name="prefix" value="/" />
  <property name="suffix" value=".jsp" />
</bean>

I have a pretty simple handler method in my controller, but I've simplified it even more for this example:

我的控制器中有一个非常简单的处理程序方法,但对于这个例子,我已经简化了它:

@RequestMapping("/groups")
public String selectGroup() {
    return "redirect:/";
}

The problem is, if I browse to https://my.domain.com/groups, I end up at http://my.domain.com/after the redirect. (In actuality my load-balancer redirects all http requests to https, but this just causes multiple browser alerts of the type "You are leaving/entering a secure connection" for folks who have such alerts turned on.)

问题是,如果我浏览到https://my.domain.com/groups,我最终会在http://my.domain.com/重定向之后。(实际上,我的负载平衡器将所有 http 请求重定向到 https,但这只会导致多个浏览器警报类型为“您正在离开/进入安全连接”,供打开此类警报的人使用。)

So the question is: how does one get spring to redirect to https when that's what the original request used?

所以问题是:当原始请求使用的是什么时,如何让 spring 重定向到 https?

采纳答案by super_aardvark

The short answer is, set the InternalResourceViewResolver's redirectHttp10Compatible property to false:

简短的回答是,将 InternalResourceViewResolver 的 redirectHttp10Compatible 属性设置为 false:

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
  <property name="prefix" value="/" />
  <property name="suffix" value=".jsp" />
  <property name="redirectHttp10Compatible" value="false" />
</bean>

You could do this on a per-request basis instead, by having your handler method return View instead of String, and creating the RedirectView yourself, and calling setHttp10Compatible(false).

您可以在每个请求的基础上执行此操作,方法是让处理程序方法返回 View 而不是 String,并自己创建 RedirectView,然后调用setHttp10Compatible(false).

(It turns out the culprit is HttpServletResponse.sendRedirect, which the RedirectView uses for HTTP 1.0 compatible redirects, but not otherwise. I guess this means it's dependent on your servlet container's implementation (?); I observed the problem in both Tomcat and Jetty.)

(事实证明罪魁祸首是 HttpServletResponse.sendRedirect,RedirectView 将其用于 HTTP 1.0 兼容重定向,但不是其他情况。我想这意味着它取决于您的 servlet 容器的实现(?);我在 Tomcat 和 Jetty 中都观察到了这个问题。 )

回答by tankthinks

Spring Boot provides this nice configuration based solutionto this if you're running behind a proxy server, simply add these two properties to your application.propertiesfile:

如果您在代理服务器后面运行,Spring Boot 提供了这个基于配置的不错的解决方案,只需将这两个属性添加到您的application.properties文件中:

server.tomcat.remote_ip_header=x-forwarded-for
server.tomcat.protocol_header=x-forwarded-proto

This works for me deploying the otherwise unchanged spring-boot-sample-web-uito Elastic Beanstalk behind an https load balancer. Without these properties the redirect on line 68 of the MessageControllerdefaults to http and hangs.

这适用于我将其他未更改的spring-boot-sample-web-ui部署到 https 负载均衡器后面的 Elastic Beanstalk。如果没有这些属性,第 68 行的重定向MessageController默认为 http 并挂起。

Hope this helps.

希望这可以帮助。

回答by Albert Bos

What worked for me is adding this to application.properties server.tomcat.use-relative-redirects=true

对我有用的是将它添加到 application.properties server.tomcat.use-relative-redirects=true

So when you have:

所以当你有:

public function redirect() {
  return "redirect:/"
}

Without the server.tomcat.use-relative-redirectsit will add a Locationheader like: http://my-host.com/. With the server.tomcat.use-relative-redirectsit will look like: /. So it will be relative to the current page from browser perspective.

如果没有server.tomcat.use-relative-redirects它,它将添加一个Location标题,如:http://my-host.com/。随着server.tomcat.use-relative-redirects它的样子:/。因此,从浏览器的角度来看,它将相对于当前页面。

回答by Janning

Are you sure?

你确定吗?

Looking at the code it seems there is no difference. Both variants call response.encodeRedirectURL(targetUrl), see Line 388 of RedirectView:

查看代码似乎没有区别。两种变体都调用 response.encodeRedirectURL(targetUrl),参见 RedirectView 的第 388 行:

if (http10Compatible) {
    // Always send status code 302.
    response.sendRedirect(response.encodeRedirectURL(targetUrl));
}
else {
    HttpStatus statusCode = getHttp11StatusCode(request, response, targetUrl);
    response.setStatus(statusCode.value());
    response.setHeader("Location", response.encodeRedirectURL(targetUrl));
}

I had the same problem, but it was triggered by setting up tomcat behind a loadbalancer. The loadbalancer does the SSL handshake and forwards to tomcat a plain http connection.

我有同样的问题,但它是由在负载均衡器后面设置 tomcat 触发的。负载均衡器执行 SSL 握手并转发给 tomcat 一个普通的 http 连接。

Solution would be to send a special Http Header in your Loadbalancer, so tomcat can "trust" this connection. Using a servlet filter should set response.isSecure flag. Then overwrite RedirectView to see if response.isSecure and handle it the right way.

解决方案是在您的负载均衡器中发送一个特殊的 Http Header,以便 tomcat 可以“信任”这个连接。使用 servlet 过滤器应该设置 response.isSecure 标志。然后覆盖 RedirectView 以查看 response.isSecure 并以正确的方式处理它。

I kept this solution short because i am not sure if it machtes the question.

我保持这个解决方案简短,因为我不确定它是否解决了这个问题。

回答by Michiel Haisma

Since Spring Boot 2.1 you have to add the following configuration to your application.properties:

从 Spring Boot 2.1 开始,您必须将以下配置添加到您的application.properties

server.use-forward-headers=true 

or application.yml:

application.yml

server:
  use-forward-headers: true

回答by erc mgddm

I add scheme="https"in file server.xml for connector with port="80":

scheme="https"在文件 server.xml 中添加了连接器port="80"

<Connector port="80" protocol="HTTP/1.1" URIEncoding="UTF-8"
connectionTimeout="20000" redirectPort="443" scheme="https" />

回答by join chi

if you use springmvc ,you can try the following:

如果您使用 springmvc ,您可以尝试以下操作:

modelAndView.setView(new RedirectView("redirect url path", true, false));