Подтвердить что ты не робот

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 при использовании исходного запроса?

4b9b3361

Ответ 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