Ejemplos incluyen X.509, Siteminder y autenticación mediante el contenedor Java EE en el que se ejecuta la aplicación. Al utilizar la autenticación previa, Spring Security debe:

  • Identificar al usuario que realiza la solicitud.

  • Obtener permisos para el usuario.

Los detalles dependerán del mecanismo de autenticación externo. El usuario puede ser identificado por la información de su certificado en el caso de X.509, o por el encabezado de solicitud HTTP en el caso de Siteminder. Si confía en la autenticación del contenedor, el usuario será identificado llamando al método getUserPrincipal() en la solicitud HTTP entrante. En algunos casos, un mecanismo externo puede proporcionar información sobre la función/los permisos del usuario, pero en otros casos, los permisos deben obtenerse de una fuente independiente, como UserDetailsService.

Pre -clases de marco de autenticación

Dado que la mayoría de los mecanismos de autenticación previa siguen el mismo patrón, Spring Security contiene un conjunto de clases que proporcionan un marco de back-end para implementar proveedores de autenticación previa. Esto le permite eliminar duplicaciones y agregar nuevas implementaciones de forma estructurada, sin tener que escribir todo desde cero. No necesita saber nada sobre estas clases si desea utilizar algo como la autenticación basada en X.509, ya que ya proporciona una opción de configuración de espacio de nombres que es más fácil de usar y de comenzar. Si necesita utilizar una configuración explícita de beans o planea escribir su propia implementación, será útil comprender cómo funcionan las implementaciones pasadas. Puede encontrar las clases en org.springframework.security.web.authentication.preauth. Aquí solo daremos una descripción general, por lo que debe consultar el Javadoc y las fuentes cuando sea necesario.

AbstractPreAuthenticatedProcessingFilter

Esta clase verifica el contenido actual del contexto de seguridad y, si vacío, intenta recuperar información del usuario de la solicitud HTTP y pasarla a AuthenticationManager. Las subclases anulan los siguientes métodos para obtener esta información:

Override AbstractPreAuthenticatedProcessingFilter
Java

protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request);
protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request);
Kotlin

protected abstract fun getPreAuthenticatedPrincipal(request: HttpServletRequest): Any?
protected abstract fun getPreAuthenticatedCredentials(request: HttpServletRequest): Any?

Después de llamarlos, el filtro creará un PreAuthenticatedAuthenticationToken que contiene los datos devueltos y los enviará para su autenticación. Por "autenticación" aquí solo nos referimos a un procesamiento adicional para posiblemente cargar las credenciales del usuario, pero respetando la arquitectura de autenticación estándar de Spring Security.

Al igual que otros filtros de autenticación de Spring Security, el filtro de autenticación previa tiene un authenticationDetailsSource, que de forma predeterminada crea un objeto WebAuthenticationDetails para almacenar información adicional, como el ID de sesión y la dirección IP de origen, en la propiedad details del objeto de Authentication. En los casos en que la información del rol del usuario se pueda obtener a partir de un mecanismo de autenticación previa, esta información también se almacenará en esta propiedad, teniendo en cuenta la información que implementa la interfaz GrantedAuthoritiesContainer. Esto permite al proveedor de autenticación leer las credenciales que se han asignado al usuario externamente. A continuación veremos un ejemplo específico.

J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource

Si el filtro está configurado con un authenticationDetailsSource que es una instancia de esta clase, las credenciales La información se obtiene llamando al isUserInRole(String role) para cada "rol asignado" de un conjunto predefinido. La clase los recibe del MappableAttributesRetriever configurado. Las posibles implementaciones incluyen codificar la lista en el contexto de la aplicación y leer la información del rol a partir de la información en la sección <security-role> del archivo web.xml. La aplicación de autenticación previa de muestra utiliza el último enfoque.

Hay un paso adicional donde los roles (o atributos) se asignan a objetos GrantedAuthority de Spring Security a través de un configurado Attributes2GrantedAuthoritiesMapper. De forma predeterminada, los nombres simplemente tienen el prefijo habitual ROLE_, pero esto brinda control total sobre la lógica operativa.

PreAuthenticatedAuthenticationProvider

El proveedor autenticado previamente solo necesita cargar el objeto UserDetails para el usuario. Lo hace delegando autoridad al servicio AuthenticationUserDetailsService. Este último es similar al UserDetailsService estándar, pero acepta un objeto Authentication en lugar de solo un nombre de usuario:


public interface AuthenticationUserDetailsService {
    UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException;
}

Esta interfaz puede tener otros usos, pero cuando se autentica previamente, permite el acceso a las credenciales que se han empaquetado en object Autenticación, que se pudo ver en el apartado anterior. Esto lo realiza la clase PreAuthenticatedGrantedAuthoritiesUserDetailsService. Alternativamente, puede delegar autoridad al UserDetailsService estándar a través de la implementación UserDetailsByNameServiceWrapper.

Http403ForbiddenEntryPoint

AuthenticationEntryPoint es responsable de iniciar el proceso de autenticación para un usuario no autenticado (si está intentando acceder a un recurso protegido), pero no se aplica en el caso de autenticación previa. Puede configurar ExceptionTranslationFilter usando una instancia de esta clase solo si no está usando la autenticación previa en combinación con otros mecanismos de autenticación. Se llamará si AbstractPreAuthenticatedProcessingFilter rechaza al usuario, lo que resultará en una autenticación nula. Llamarlo siempre devuelve un código de respuesta de 403-forbidden.

Implementaciones específicas

La autenticación basada en X.509 se describe en un capítulo separado. Aquí veremos algunas clases que brindan soporte para otros escenarios de autenticación previa.

Solicitar autenticación de encabezado (Siteminder)

Un sistema de autenticación externo puede pasar información a la aplicación configurando ciertos encabezados en la solicitud HTTP. Un buen ejemplo de este tipo de sistema es Siteminder, que pasa el nombre de usuario en el encabezado SM_USER. Este mecanismo es compatible con la clase RequestHeaderAuthenticationFilter, que simplemente extrae el nombre de usuario del encabezado. De forma predeterminada, el nombre del encabezado es SM_USER. Para obtener más información, consulte javadoc.

Tenga en cuenta que cuando se utiliza un sistema como este, el marco no realice cualquier No hay comprobaciones de autenticación, por lo que es fundamental que el sistema externo esté configurado correctamente para proteger cualquier acceso a la aplicación. Si un atacante puede falsificar los encabezados de la solicitud original de tal manera que no pueda ser detectado, entonces puede elegir cualquier nombre de usuario a su discreción.

Ejemplo de configuración usando Siteminder

Una configuración típica que utiliza este filtro se ve así:


<security:http>
<!-- Configuración http adicional omitida -->
<security:custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />
</security:http>
<bean id="siteminderFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
<property name="principalRequestHeader" value="SM_USER"/>
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService">
	<bean id="userDetailsServiceWrapper"
          class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
	<property name="userDetailsService" ref="userDetailsService"/>
	</bean>
</property>
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="preauthAuthProvider" />
</security:authentication-manager>

Aquí hemos asumido que el espacio de nombres de seguridad se utiliza para la configuración. También supone que se ha agregado UserDetailsService (llamado "userDetailsService") a la configuración para cargar roles de usuario.

Autenticación a nivel de contenedor Java EE

Clase La J2eePreAuthenticatedProcessingFilter recuperará el nombre de usuario de la propiedad userPrincipal para HttpServletRequest. El uso de este filtro normalmente se combina con el uso de roles Java EE, como se describe anteriormente en la subsección J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.

El proyecto de muestra tiene aplicación de muestraque utiliza este enfoque, así que toma el código de GitHub y mira el archivo de contexto de la aplicación si lo deseas. Estás interesado.