2010-08-03 25 views
36

Lo resolví yo mismo, pero pasé tanto tiempo descubriendo una solución tan simple, pensé que merecía ser documentada aquí.Spring MVC "redirect:" prefix siempre redirecciona a http, ¿cómo puedo mantenerlo en https?

Tengo una configuración típica MVC Spring 3 con un 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> 

Tengo un método de control bastante simple en mi controlador, pero he simplificado aún más para este ejemplo:

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

El problema es que si navego a https://my.domain.com/groups, termino en http://my.domain.com/ después de la redirección. (En realidad, mi equilibrador de carga redirige todas las solicitudes http a https, pero esto solo causa varias alertas del navegador del tipo "Usted está dejando/ingresando una conexión segura" para las personas que tienen activadas tales alertas)

Así que la La pregunta es: ¿cómo se consigue que la primavera redirija a https cuando eso es lo que usaba la solicitud original?

+0

¿Qué hay de usar sólo "redirigir". Usar una URL relativa después de la redirección debería funcionar también. – qkrijger

Respuesta

46

La respuesta corta es, establezca la propiedad redirectHttp10Compatible del InternalResourceViewResolver 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> 

Usted puede hacer esto en una base por solicitud de cambio, por tener su manejador de retorno del método vista en lugar de cuerdas, y la creación de la RedirectVerse a sí mismo y llamar al setHttp10Compatible(false).

(Resulta que el culpable es HttpServletResponse.sendRedirect, que RedirectView utiliza para redireccionamientos compatibles con HTTP 1.0, pero no de otra manera. Supongo que esto significa que depende de la implementación de su contenedor de servlets (?); Observé el problema en ambos Tomcat y Jetty.)

5

¿Estás seguro?

Mirando el código parece que no hay diferencia. Ambas variantes llamar response.encodeRedirectURL (targetUrl), véase la línea 388 de 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)); 
} 

que tenían el mismo problema, pero fue provocada por la configuración de Tomcat detrás de un equilibrador de carga. El loadbalancer realiza el protocolo de enlace SSL y reenvía a tomcat una conexión http simple.

La solución sería enviar un encabezado Http especial en su Loadbalancer, por lo que tomcat puede "confiar" en esta conexión. El uso de un filtro de servlet debe establecer la bandera response.isSecure. Luego sobrescriba RedirectView para ver si response.isSecure y maneje de la manera correcta.

Mantuve esta solución corta porque no estoy seguro de si se trata de una cuestión.

+0

Imagino que response.encodeRedirectURL no toca el protocolo y que es response.sendRedirect que establece el protocolo en http. Su solución probablemente funcione, pero la mía es más fácil (a costa de la compatibilidad HTTP/1.0, por supuesto). –

18

primavera de arranque proporciona this nice configuration based solution a esto si se está ejecutando un servidor proxy, sólo tiene que añadir estas dos propiedades a su application.properties archivo:

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

Esto funciona para mí el despliegue de la otra manera sin cambios spring-boot-sample-web-ui a Elastic Beanstalk detrás un balanceador de carga https. Sin estas propiedades, la redirección en la línea 68 del MessageController se predetermina a http y se cuelga.

Espero que esto ayude.

+0

Esta debería ser la solución aceptada si su caso de uso es Usuario - LoadBalancer - ¡Aplicación! –

+0

¿Cómo se da más de un voto a favor? ¡Este es definitivamente el derecho anwer! – simon

+1

Gracias. Esto ayudó a mi aplicación que estaba detrás de un equilibrador de carga. Los parámetros de configuración han cambiado ligeramente. server.tomcat.remote-ip-header = x-forward-for server.tomcat.protocol-header = x-forward-proto –

0

si utiliza SpringMVC, puede intentar lo siguiente:

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