2011-02-17 13 views
14

Actualicé mi aplicación GWT/GXT con autorización LDAP básica mediante autenticación HTTP básica. Funciona bien cuando inicio un nuevo navegador: recibo la solicitud y me autorizo ​​contra el LDAP corporativo. Mi problema: no puedo cerrar la sesión a menos que cierre/vuelva a abrir el navegador. Puedo depurar y ver cómo SecurityContextLogoutHandler#logout se llama y el siguiente código se ejecutaSeguridad de primavera: no se puede cerrar sesión

if (invalidateHttpSession) { 
     HttpSession session = request.getSession(false); 
     if (session != null) { 
      session.invalidate(); 
     } 
    } 

    SecurityContextHolder.clearContext(); 

Sin embargo, al parecer, ha de volver a cargar ningún efecto como el sitio y nunca conseguir otro indicador de autenticación HTTP a menos que reinicie el navegador (incluso borrar la memoria caché/las cookies no ayudarán). Aquí es parte relevante de applicationContext.xml

<security:http auto-config='true'> 
    <security:intercept-url pattern="/reports/**" access="ROLE_USER" /> 
    <security:http-basic /> 
    <security:logout logout-url="/reports/logout" 
       logout-success-url="/reports/Application.html" />  
</security:http> 

traté de definir encargo LogoutSuccessHandler y hacer authentication.setAuthenticated(false); sino que también tiene efecto

nada aquí que me falta aquí? Su ayuda será muy apreciada

Respuesta

22

OK. después de pasar demasiado tiempo con esto, creo que tengo la respuesta. Es simple: uno no puede salir de la autenticación HTTP básica usando tecnología del lado del servidor. Básicamente, la cadena de autorización está decodificada en base 64 en el encabezado HTTP y cuando la página protegida se carga en el navegador, el token de seguridad se repobla, así que no importa la frecuencia con que lo borre en el servidor, se resucita cada vez que se llama a la página. Supongo que es posible jugar algunos trucos ingeniosos en el lado del navegador, pero eso sería frágil y poco fiable

En mi caso cambiaré a la autenticación basada en formularios que da mucho mejor control sobre el proceso de inicio/cierre de sesión.

voy a aferrarse aceptar mi propia respuesta a favor alguien que sale con solución aceptable

+0

Estoy buscando lo mismo (después de mucho tiempo), pero me cuesta creer que no se pueda hacer nada. – Snekse

3

Uhm ... extraño. No veo nada mal con su configuración. Realmente no necesita definir ningún manejador de cierre de sesión personalizado, ya que Spring Security debe manejarlo.

probar esto, en lugar de definir su logout-url, utilice el enlace de desconexión por defecto: -

... 
<security:logout logout-success-url="/reports/Application.html" />  
... 

A continuación, utilice /j_spring_security_logout cerrar la sesión.

¿Funciona esto en absoluto?

+0

No es sorprendente que tenga el mismo efecto. Como dije, va a través de la lógica LogoutHandler, es solo que aparentemente no hace nada – Bostone

+0

No hay nada de malo en mi cableado. La verdad es que HTTP básico no es compatible con el cierre de sesión – Bostone

0
<logout invalidate-session="true" logout-url="/reports/logout" 
     logout-success-url="/reports/Application.html" /> 

acaba de establecer la sesión invalidar a 'verdadero' y ver si funciona.

verificación si esta listner está allí en su web.xml:

<!-- Security: to listen session requests --> 
<listener> 
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class> 
</listener> 

Si las cosas anteriores no funcionan entonces puede intentar siguiente solución. Creo que el problema es con su siguiente línea,

<security:intercept-url pattern="/reports/**" access="ROLE_USER" /> 

Por encima de la línea significa que agregó el acceso a ROLE_USER yout '/ informes/**' enlace. Pero después del cierre de sesión, está dando la misma URL para el éxito de cierre de sesión. entonces, ¿cómo funcionará? Cambie la ubicación de su página de éxito de cierre de sesión o puede agregar la siguiente línea en la etiqueta http.

<intercept-url pattern="/reports/Application.html" filters="none" /> 
+0

Lo siento, ninguna de sus sugerencias funcionó. invalidate-session = true es por defecto, agregué la página listener y logout. Sin embargo, creo que la página de cierre de sesión es irrelevante (es/de forma predeterminada) porque incluso si falta, ya que estoy usando el inicio de sesión HTTP básico tan pronto como cierre sesión, debería aparecer el mensaje de inicio de sesión y eso es exactamente lo que no está sucediendo. Puedo recorrer el código de inicio de sesión que se ejecuta, pero no hace ninguna diferencia. A menos que mate el navegador, permaneceré conectado al – Bostone

+0

. No sé quién dio a esta solución un conteo positivo, pero está fundamentalmente fuera del punto. Vea mi propia respuesta – Bostone

0

Creo firmemente que estás en lo correcto. No puede invalidar una autenticación básica o implícita sin hacerlo en el navegador. Incluso allí será extremadamente difícil si no imposible. Francamente, ni siquiera puedo pensar en una forma de hacerlo allí (que no sea tratar de cerrar el navegador).

Como ha señalado, el problema es que, aunque invalide todo lo relacionado con el servidor, le ha dado al navegador todo lo que necesita para generar automáticamente una nueva sesión de autenticación. La única forma de aclarar eso es borrar el navegador. Incluso reiniciar el servidor no desactivará la capacidad del navegador para crear una nueva autenticación, lo cual es una buena indicación de que no podrá lograr esto en el lado del servidor sin invalidar el contrato de autenticación básica o implícita.

Francamente, esto parece un agujero de seguridad bastante importante en los navegadores en el sentido de que nunca debe dejar un navegador ejecutándose en un servidor de acceso abierto después de autenticarse en un sitio con autenticación básica o resumida.

La autenticación de formulario puede ser su mejor opción porque no le está dando al navegador información sobre cómo resucitar una autenticación a menos que permita una cookie de recallme. Incluso allí, puedes borrar la cookie al cerrar la sesión para que sea más fácil.

4

Bostone es básicamente correcto en que no puede manejar este servidor. Hay, sin embargo, a bit of a hack that's available.

La respuesta corta es redirigir al usuario a la URL que desea que aterrice, pero prefijo con un nombre de usuario incorrecto seguido de @. Así como un ejemplo feo,

<security:logout logout-url="/reports/logout" 
    logout-success-url="http://[email protected]/reports/Application.html" /> 

Lo ideal sería implementar un controlador que hacer esto para usted, pero para fines de ilustración, creo que obtiene el concepto de ancho.

+1

Claro que es un truco, pero está funcionando – yunandtidus

+1

Desafortunadamente, esto ya no parece funcionar de manera confiable en los navegadores recientes, presumiblemente debido al uso de ese tipo de URL en los correos electrónicos de phishing. Chrome simplemente ignora el nombre de usuario, Firefox muestra una advertencia de que estás intentando iniciar sesión en un sitio que no necesita un inicio de sesión, y Safari muestra una gran Alerta de Phishing roja. – Zorac

0

Una forma que he encontrado para hacer esto es devolver respuestas HTTP 401. Algunas pruebas rápidas muestran que esto funciona en las versiones de macOS de Safari, Chrome & Firefox. El código que utilizo es esencialmente equivalente a esto:

@RequestMapping(value="/logout",method=RequestMethod.POST) 
public void logout(HttpServletRequest request, HttpServletResponse response, HttpSession session) { 
    session.setAttribute(LOGOUT_SESSION_KEY, true); 
    response.setStatus(303); 
    response.addHeader("Location", URL_OF_APPLICATION_HOME_PAGE); 
} 

@RequestMapping("/") 
public void home(HttpServletRequest request, HttpServletResponse response, HttpSession session) { 
    if (Boolean.TRUE.equals(session.getAttribute(LOGOUT_SESSION_KEY))) { 
     if (request.getHeader("Authorization") != null) { 
      session.invalidate(); 
     } 

     response.setStatus(401); 
     response.addHeader("WWW-Authenticate", "Basic realm=\"" + HTTP_BASIC_REALM + "\""); 
     return; 
    } 

    /* Generate home page */ 
} 

El truco es que por lo general tiene que devolver la cabecera 401 veces - después de la primera, el navegador volverá a intentar con sus credenciales almacenadas en caché (el envío de la "Autorización" encabezado, en cuyo punto destruimos la sesión anterior del usuario), el segundo parece borrarlos y solicita un inicio de sesión.

Cuestiones relacionadas