tutorial example java spring-security

java - example - ¿Cómo habilitar inmediatamente la autorización después de actualizar la autorización del usuario en la seguridad de Spring?



spring security xml (7)

Estoy utilizando Spring-Security Framework. Cuando actualizo los permisos, no surte efecto inmediatamente. Tengo que salir del usuario actual (significa cerrar sesión) y luego volver a visitar (significa iniciar sesión) será actualizar el permiso del usuario. .

¿Es una forma que habilite inmediatamente la autorización después de actualizar la autorización del usuario en la seguridad de Spring?


Como no proporcionó los detalles exactos en su pregunta, asumo que tiene una situación en la que:

  1. Usted está suministrando un UserDetailsService para cargar un UserDetails cuando un usuario intenta iniciar sesión
  2. Como parte de ese servicio, está consultando una base de datos / DAO para cargar detalles sobre los permisos de un usuario y está configurando las autorizaciones otorgadas en función de esto
  3. Que cuando dices "Cuando actualizo los permisos" te refieres a actualizar los permisos del usuario en la base de datos (o en lo que estés almacenando datos).

Si es así, entonces lo que está viendo es por diseño: Spring Security solo carga los Detalles de Usuario para el usuario la primera vez, cuando intenta iniciar sesión, y luego lo almacena en Sesión a partir de entonces. En general, esto tiene sentido, ya que evita que la aplicación tenga que realizar las mismas consultas sobre los detalles del usuario en cada solicitud. Además, los permisos de un usuario generalmente no cambian a lo largo del 99.9% de sus visitas.

Para cambiar este comportamiento, es posible que desee agregar un comando / página "actualizar" en algún lugar que active algún código (que tendrá que escribir) que volverá a consultar UserDetailsService y reemplazará UserDetails en SecurityContext. No creo que haya ninguna forma integrada de hacer esto.


El siguiente hilo explica cómo recargar su solicitud de usuario / principal:

Recargar objeto UserDetails desde la base de datos cada solicitud en Spring Security


Revelación completa Soy el autor de la pregunta y la respuesta de la pregunta en el enlace anterior.


La solución de Gandalf es válida pero no completa. Para que los nuevos permisos puedan ser considerados por la seguridad de Spring (por ejemplo, permitir el acceso a páginas que anteriormente no estaban disponibles), debe crear un nuevo objeto de autenticación (por ejemplo, new UsernamePasswordAuthenticationToken) que contenga la nueva lista de autoridades.


No es suficiente para restablecer el contexto de Thread Local, también necesita actualizar la sesión:

UserContext userContext = (UserContext) context.getAuthentication().getPrincipal(); if (userContext != null && userContext.getUsername() != null) { //This is my function to refresh the user details UserDetailsBean userDetails = getUserDetailsBean(userContext.getUsername()); Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication instanceof UsernamePasswordAuthenticationToken) { UsernamePasswordAuthenticationToken auth = (UsernamePasswordAuthenticationToken) authentication; auth.setDetails(userDetails); } return userDetails; } else { throw new ServiceException("User not authenticated"); } request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());

Al menos en google appengine, la sesión no es una referencia y al modificar el subproceso local no se actualiza automáticamente, debe iniciar sesión manualmente en su objeto.


Puede crear su propia implementación de la interfaz UserDetails que se devuelve de su mecanismo de autenticación, que le permite acceder a las Autoridades Granted []. Luego agregue su nueva autoridad directamente a ese objeto UserDetails. Es posible que tenga problemas si un usuario puede tener varias sesiones abiertas a la vez (o si varios usuarios comparten el mismo inicio de sesión genérico), que los nuevos permisos solo se verán en la sesión que haya modificado.


Puede establecer siempre Reautenticar en su AbstractSecurityInterceptor como este

<bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor"> <property name="alwaysReauthenticate" value="true"/> ... </bean>

Por supuesto, debe prestar atención porque el 99,9% no necesita reautenticación. Como la autenticación puede usar una base de datos o algo más, su rendimiento puede degradarse. Pero, por lo general, tiene un caché, como el 2º nivel con hibernación, por lo que cargar los detalles del usuario cada vez debería ser una operación de solo memoria en todos los casos donde las autoridades no hayan cambiado.


Puedes probar esto

SecurityContextHolder.getContext().setAuthentication(SecurityContextHolder.getContext().getAuthentication());