Spring MVC "redirect:" префикс всегда перенаправляет на http - как мне заставить его оставаться на https?
Я решил это сам, но я так долго обнаружил такое простое решение, я полагал, что это заслуживает того, чтобы быть зарегистрированным здесь.
У меня есть типичная установка 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, но это просто вызывает несколько предупреждений браузера типа "Вы уходите/входите в безопасное соединение" для людей, у которых есть такие предупреждения.)
Итак, возникает вопрос: как получить Spring для перенаправления на https при использовании исходного запроса?
Ответы
Ответ 1
Короткий ответ: присвойте свойству 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>
Вместо этого вы можете сделать это по принципу запроса, используя метод обработчика return View вместо String и создавая сам RedirectView и вызывающий setHttp10Compatible(false)
.
(Получается, что виновником является HttpServletResponse.sendRedirect, который RedirectView использует для перенаправлений, совместимых с HTTP 1.0, но не иначе. Я предполагаю, что это означает, что он зависит от реализации контейнера контейнера сервлетов (?), я заметил проблему в Tomcat и Jetty.)
Ответ 2
Spring Boot предоставляет это хорошее решение для конфигурации, если вы работаете за прокси-сервером, просто добавьте эти два свойства в свой файл application.properties
server.tomcat.remote_ip_header=x-forwarded-for
server.tomcat.protocol_header=x-forwarded-proto
Это работает для меня развертывания в противном случае неизмененного spring-boot-sample-web-ui для эластичного бобового стежка за балансировщиком нагрузки https. Без этих свойств перенаправление по строке 68 MessageController
по умолчанию соответствует http и зависает.
Надеюсь, что это поможет.
Ответ 3
Вы уверены?
Глядя на код, кажется, нет никакой разницы. Оба варианта вызывают response.encodeRedirectURL(targetUrl), см. Строку 388 RedirectView:
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-квитирование и переадресации, чтобы передать обычное http-соединение.
Решение было бы отправить специальный Http Header в ваш Loadbalancer, так что tomcat может "доверять" этому соединению. Использование фильтра сервлета должно установить response.isSecure. Затем перезапишите RedirectView, чтобы увидеть, отвечает ли response.isSecure и обрабатывает его правильным способом.
Я оставил это решение коротким, потому что я не уверен, что он задает вопрос.
Ответ 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
это будет выглядеть так: /
. Так что это будет относительно текущей страницы с точки зрения браузера.
Ответ 5
если вы используете springmvc, вы можете попробовать следующее:
modelAndView.setView(new RedirectView("redirect url path", true, false));
Ответ 6
Для сервера Tomcat. Я добавляю scheme
свойств со значением https
в файл server.xml для коннектора с port="80
:
<Connector port="80" protocol="HTTP/1.1" URIEncoding="UTF-8" connectionTimeout="20000" redirectPort="443" scheme="https"/>
Мои результаты:
redirect if not authorized:
http->https
https->https
redirect if authorized:
http->http
https->https
redirect from login form page:
http->https
https->https
Почему нет redirectHttp10Compatible
? Если установить свойство redirectHttp10Compatible
с значением false
для viewResolver, мой результат:
redirect from login form page:
http->http
! https->http !
И перенаправление с помощью @RequestMapping({"/"})
в моем контроллере вернет пустую страницу.
Ответ 7
Я добавляю scheme="https"
в файл server.xml для соединителя с port="80"
:
<Connector port="80" protocol="HTTP/1.1" URIEncoding="UTF-8"
connectionTimeout="20000" redirectPort="443" scheme="https" />
Ответ 8
Начиная с Spring Boot 2.1, вы должны добавить следующую конфигурацию в ваш application.properties
:
server.use-forward-headers=true
или application.yml
:
server:
use-forward-headers: true