Spring Security proporciona un paquete que puede delegar solicitudes de autenticación al Servicio de autenticación y autorización de Java (JAAS). Este paquete se describe en detalle a continuación.

Proveedor de autenticación Jaas abstracto

AbstractJaasAuthenticationProvider es la base para las implementaciones de AuthenticationProvider proporcionadas en JAAS. Las subclases deben implementar un método que cree un LoginContext. AbstractJaasAuthenticationProvider tiene una serie de dependencias que se pueden inyectar en él, que se describen a continuación.

Manejador de devolución de llamadas JAAS

La mayoría de los LoginModule de JAAS requieren algún tipo de devolución de llamada. Estas devoluciones de llamada se utilizan normalmente para recuperar el nombre de usuario y la contraseña del usuario.

Cuando se implementa utilizando Spring Security, Spring Security es responsable de esta interacción del usuario (a través de un mecanismo de autenticación). Por lo tanto, para cuando la solicitud de autenticación se pase a JAAS, el mecanismo de autenticación de Spring Security ya habrá llenado completamente el objeto Authentication que contiene toda la información requerida por el LoginModule de JAAS. .

Por lo tanto, el paquete JAAS para Spring Security contiene dos controladores de devolución de llamada estándar, JaasNameCallbackHandler y JaasPasswordCallbackHandler. Cada uno de estos controladores de devolución de llamada implementa JaasAuthenticationCallbackHandler. En la mayoría de los casos, estos controladores de devolución de llamadas se pueden utilizar simplemente sin tener que entender su mecánica interna.

Para aquellos que requieren control total sobre la lógica de devolución de llamada, AbstractJaasAuthenticationProvider envuelve internamente estas instancias de JaasAuthenticationCallbackHandler con InternalCallbackHandler. InternalCallbackHandler es una clase que en realidad implementa la interfaz CallbackHandler normal de JAAS. Cada vez que se utiliza un LoginModule desde JAAS, se le pasa una lista de instancias de InternalCallbackHandler configuradas en el contexto de la aplicación. Si LoginModule solicita una devolución de llamada para InternalCallbackHandlers, la devolución de llamada a su vez se pasa a las instancias empaquetadas de JaasAuthenticationCallbackHandler.

Concedente de autoridad JAAS

JAAS trabaja con directores. En JAAS, incluso los "roles" se representan como directores. Spring Security, por otro lado, funciona con objetos Authentication. Cada objeto Authentication contiene un principal y múltiples GrantedAuthority. Para facilitar la correlación entre estos diferentes conceptos, el paquete JAAS en Spring Security contiene la interfaz AuthorityGranter.

El

AuthorityGranter es responsable de validar el principal JAAS y devuelve un conjunto de String que representa la autoridad otorgada al principal. Para cada cadena de permiso devuelta, AbstractJaasAuthenticationProvider crea un JaasGrantedAuthority (que implementa la interfaz GrantedAuthority de Spring Security) que contiene la cadena de autoridad y el principal JAAS. que se pasó AuthorityGranter. El AbstractJaasAuthenticationProvider obtiene los principales JAAS autenticando primero con éxito las credenciales del usuario utilizando el LoginModule de JAAS y luego accediendo al LoginContext devuelto. Se realiza una llamada a LoginContext.getSubject().getPrincipals() y cada principal recibido se pasa a cada AuthorityGranter definido en AbstractJaasAuthenticationProvider.setAuthorityGranters(List) propiedad.

Spring Security no contiene ningún AuthorityGranters de producción porque cada principal JAAS tiene un valor específico de la implementación. Sin embargo, las pruebas unitarias tienen un TestAuthorityGranter que demuestra claramente cómo funciona una implementación simple de AuthorityGranter.

Proveedor de autenticación Jaas predeterminado

El

DefaultJaasAuthenticationProvider le permite inyectar un objeto Configuration JAAS en él como una dependencia. Luego crea un LoginContext utilizando la Configuration inyectada desde JAAS. Esto significa que DefaultJaasAuthenticationProvider no está vinculado a una implementación de Configuration específica como lo está JaasAuthenticationProvider.

Configuración en memoria

Para facilitar la implementación de Configuration en DefaultJaasAuthenticationProvider, existe una implementación en memoria llamada InMemoryConfiguration de forma predeterminada. El constructor de implementación toma un Map en el que cada clave representa un nombre de configuración de inicio de sesión y el valor es un Array que consta de un AppConfigurationEntry. InMemoryConfiguration también admite un Array estándar que consta de objetos AppConfigurationEntry, que se utilizará si no se encuentra ninguna asignación en el especificado Map. Para obtener más información, consulte el javadoc de nivel de clase en InMemoryConfiguration.

Ejemplo de configuración de DefaultJaasAuthenticationProvider

Aunque la configuración de Spring para InMemoryConfiguration puede estar más llena que los archivos de configuración JAAS estándar, usarlo en combinación con DefaultJaasAuthenticationProvider es más flexible que usar JaasAuthenticationProvider , ya que no depende de la implementación estándar de Configuration.

El siguiente es un ejemplo de una configuración de DefaultJaasAuthenticationProvider usando InMemoryConfiguration. Tenga en cuenta que las implementaciones personalizadas de Configuration se pueden implementar fácilmente en DefaultJaasAuthenticationProvider.

<bean id="jaasAuthProvider"
class="org.springframework.security.authentication.jaas.DefaultJaasAuthenticationProvider">
<nombre de propiedad="configuración">
<bean class="org.springframework.security.authentication.jaas.memory.InMemoryConfiguration">
<constructor-arg>
<mapa>
<!--
SPRINGSECURITY es el nombre de contexto de inicio de sesión predeterminado
para AbstractJaasAuthenticationProvider
-->
<tecla de entrada="SPRINGSECURITY">
<matriz>
<bean class="javax.security.auth.login.AppConfigurationEntry">
<constructor-arg value="sample.SampleLoginModule" />
<constructor-arg>
<util:campo estático constante=
"javax.security.auth.login.AppConfigurationEntry$LoginModuleControlFlag.REQUIRED"/>
</constructor-arg>
<constructor-arg>
<mapa></mapa>
</constructor-arg>
</frijol>
</matriz>
</entrada>
</mapa>
</constructor-arg>
</frijol>
</propiedad>
<nombre de propiedad="autoridadGranters">
<lista>
<!-- Necesitará escribir su propia implementación de AuthorityGranter -->
<bean class="org.springframework.security.authentication.jaas.TestAuthorityGranter"/>
</lista>
</propiedad>
</bean>

Proveedor de autenticación Jaas

JaasAuthenticationProvider supone que la Configuración predeterminada es una instancia de ConfigFile. Esta suposición se realiza para intentar actualizar Configuración. El JaasAuthenticationProvider luego usa la Configuration estándar para crear un LoginContext.

Supongamos que tenemos un archivo de configuración de inicio de sesión JAAS, /WEB-INF/login.conf, con el siguiente contenido:

JAASTest {
sample.SampleLoginModule requerido;
};

Como todos los beans de Spring Security, JaasAuthenticationProvider se configura a través del contexto de la aplicación. Las siguientes definiciones coincidirán con el archivo de configuración JAAS de inicio de sesión anterior:

<bean id="jaasAuthenticationProvider"
class="org.springframework.security.authentication.jaas.JaasAuthenticationProvider">
<property name="loginConfig" value="/WEB-INF/login.conf"/>
<nombre de propiedad="loginContextName" valor="JAASTest"/>
<nombre de propiedad="callbackHandlers">
<lista>
<frijol
class="org.springframework.security.authentication.jaas.JaasNameCallbackHandler"/>
<frijol
class="org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler"/>
</lista>
</propiedad>
<nombre de propiedad="autoridadGranters">
<lista>
<bean class="org.springframework.security.authentication.jaas.TestAuthorityGranter"/>
</lista>
</propiedad>
</bean>

Ejecutar como Asunto

JaasApiIntegrationFilter, si se agrega a la configuración, intentará ejecutarse como Asunto para JaasAuthenticationToken. Esto significa que se puede acceder a Asunto con:

Asunto asunto = Asunto.getSubject(AccessController.getContext());

Esta integración se puede configurar fácilmente utilizando el atributo jaas-api-provision. Esta característica es útil cuando se integra con API heredadas o externas que dependen de la población de entidades JAAS.