Spring MVC“redirect:”前缀总是重定向到http - 如何让它保持在https?

时间:2010-08-03 22:01:23

标签: spring spring-mvc

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

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

<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>

我的控制器中有一个非常简单的处理程序方法,但是我在这个例子中对它进行了更简化:

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

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

所以问题是:当原始请求使用时,如何重新定向到https?

8 个答案:

答案 0 :(得分:51)

简短的回答是,将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>

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

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

答案 1 :(得分:31)

如果您在代理服务器后面运行,则Spring Boot会为此提供this nice configuration based solution,只需将这两个属性添加到您的application.properties文件中:

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

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

希望这有帮助。

答案 2 :(得分:6)

你确定吗?

查看代码似乎没有区别。两种变体都调用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));
}

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

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

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

答案 3 :(得分:4)

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

因此,当您拥有:

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

如果没有server.tomcat.use-relative-redirects,它将添加一个Location标头,例如:http://my-host.com/。 使用server.tomcat.use-relative-redirects时,它看起来像:/。 因此,从浏览器角度来看,它将相对于当前页面。

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

我将文件{。{1}}添加到文件{。{1}}中的连接器:

scheme="https"

答案 6 :(得分:0)

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

server.use-forward-headers=true 

application.yml

server:
  use-forward-headers: true

答案 7 :(得分:0)

我也遇到了同样的问题...当重定向到 http 而不是 HTTPS 时,以下更改完成:

RedirectView redirect = new RedirectView("/xyz",true);
redirect.setExposeModelAttributes(false);
redirect.setHttp10Compatible(false);
mav = new ModelAndView(redirect);