java - Enganche en el proceso donde el contenedor solicita roles del usuario de LDAP
security java-ee (2)
Puede personalizarlo utilizando Spring Security, autenticando contra LDAP y configurando el administrador de autenticación / proveedor de autenticación:
<security:authentication-manager>
<security:authentication-provider user-service-ref="userDetailsService">
<security:jdbc-user-service data-source-ref="dataSource"
authorities-by-username-query="select AUTHORITIES.AUTHORITIES_AUTH from AUTHORITIES, USERS where AUTHORITIES.AUTHORITIES_USER_ID = USERS.USERS_ID and ..."/>
En mi aplicación utilizo la autenticación basada en formularios con un LDAP-Realm. Para autorización, uso una base de datos. Como yo entiendo, esto funciona de la siguiente manera
App --> (user, pass) --> LDAP
<-- OK, user exists --
--> ask for security roles for ''user'' --> JACC / Database
<-- Administrator --
¿Puedo conectarme al proceso en el que mis llamadas de aplicaciones ask for security roles for ''user''
?
Fondo:
LDAP dice: Okay, ''user'' is authentified
Base de datos: give me all roles where username = user
Y ahora quiero personalizar la consulta de la base de datos: give me all roles where username = ''user'' AND some more attributes
¿Es esto de alguna manera posible?
TL; DR: Eche un vistazo a esto y a aquello para una solución de muestra.
Lo que solicite dependerá del grado de flexibilidad que ofrezca la función específica del proveedor que utilice; su producto puede o no permitirle extender el comportamiento de esa clase de LoginModule
/ Realm
/ IdentityStore
/ lo que sea que se llame clase patentada, o incluso simplemente escribir una consulta SQL en algunas UI administrativas campo de entrada. La conclusión es que es una funcionalidad no estándar.
En el lado estándar de Java EE del espectro, están los SPIS JASPIC (autenticación de usuario / mensaje) y JACC (autorización). Ambos se pueden usar para recuperar información relacionada con la seguridad perteneciente a sus usuarios desde alguna tienda externa. Lo que JASPIC no puede hacer es cambiar las funciones de un usuario después de la autenticación; es decir, durante la duración de una solicitud autenticada 1, las funciones del usuario son fijas . JASPIC tampoco puede asignar significado a esos roles; para ello, son simplemente String
que el AS derivará, de alguna manera de propiedad, del Principal
grupo. JACC, por otro lado, puede hacer esas cosas, ya que establece una "base de reglas" ( Policy
pensamiento) que asocia de manera precisa los roles, los directores y los Permission
, y puede consultarse en todas y cada una de las interacciones usuario-sistema. JACC también puede anular o modificar la interpretación de las restricciones de seguridad de Java EE expresadas mediante descripciones y anotaciones de implementación.
Incluiré una solución basada en JASPIC en esta publicación e ignoraré JACC en su mayor parte, porque:
- Es posible que no necesite la flexibilidad adicional que JACC ofrece.
- El empleo de una solución de proveedor de JACC personalizada requiere bastante trabajo y todavía no es 100% estándar debido a la asignación de grupos a rol específicos de AS.
- No conozco un proyecto de código abierto que use un proveedor personalizado de JACC para lograr algo significativo; El perfil completo de Java EE: la implementación de AS es la única excepción, ya que tienen el mandato de implementar la especificación y, en ocasiones, también usan internamente sus proveedores de JACC (como p. Ej., En el caso de GlassFish).
- Todavía hay mucha confusión en torno a JASPIC (muchos desarrolladores aún no saben que existe) que es la más simple de las dos especificaciones. Es absolutamente razonable hacer que JASPIC sea conocido y "accesible" a más personas antes de pasar a cubrir JACC.
- Si bien ahora hay más que unos pocos ejemplos excelentes en JASPIC en línea, como los proyectos que implementan la autenticación real a través de proveedores de JASPIC, corrígeme si me equivoco, todavía no he encontrado un ejemplo JASPIC completo en SO.
Algunas observaciones sobre lo que sigue:
- Sin garantía / uso bajo su propio riesgo / no me demande si su aplicación / AS / sistema explota o es pirateado por extraterrestre / etc.
- Por favor, trate de ignorar los puntos donde, en su opinión, la optimización, el mejor diseño u otras mejoras hubieran sido esenciales. Sí, podría volver a usar las conexiones DB / LDAP; validar los nombres de usuario insertados en los filtros de búsqueda LDAP; se preocupe más por la seguridad de los hilos; usa TLS; devuelve un 400 para cargas útiles XML no bien formadas .... Abordar esas preocupaciones está fuera del alcance de la solución provista. ¿¿Disculpe?? ¿Te preguntas dónde están las pruebas de la unidad ? Lo siento, nunca he oído hablar del término! :)
- Se proporcionan dos SAM concretamente realizando autenticación y recuperación de grupos (roles): un "independiente", que realiza ambas tareas por sí mismo, y uno "de delegación", que, como su nombre indica, demuestra cómo un SAM puede delegar la autenticación real trabajar con un
LoginModule
(LM) de JAAS, empleando el perfil de puente JASPIC LoginModule . El último SAM requiere una configuración / adaptación adicional, tanto en el AS como en el nivel de origen per se, excepto si está utilizando GlassFish. Se proporciona un ejemplo de acompañamiento entrada JAASlogin.conf
. - Las clases de proveedores se probaron contra GlassFish 4.1. Se esfuerzan por seguir siendo compatibles con las especificaciones y, por lo tanto, deberían trabajar realmente en su AS (obviamente, con excepción del segundo SAM), siempre que su producto implemente el perfil Full Java EE (6, preferiblemente 7). Lo siento si no lo hace; y no, no probaré en su AS.
- Puede evitar el estudio / uso de las implementaciones
AuthConfigProvider
yServerAuthConfig
, pero luego tendrá que registrar el SAM real conAuthConfigFactory
su producto de forma patentada (mediante unfoo-web.xml
específico del proveedor y / o el uso posterior de las herramientas de implementación / administrativas ) Además, no tendrá el SAM implementando la interfazServerAuthContext
y tendrá que cargar lasProperties
adjuntas desde el SAM. Su AS instanciará las clases que faltan para usted, posiblemente reutilizando unAuthConfigProvider
"global" y / oServerAuthConfig
que haya preconfigurado para todas las aplicaciones y capas de mensajes. Tenga en cuenta que, dependiendo de si reutilizaServerAuthConfig
yServerAuthContext
instanciados entre las solicitudes (casi nunca el caso especialmente con este último), el ciclo de vida de su SAM puede verse afectado. - El mapeo de grupo a rol no está cubierto ya que es específico del contenedor.
- Incluí comentarios donde sea que quisiera hacerlo. No todos son (completamente) inútiles. Con la ayuda de la especificación, el código debe ser comprensible, pero no dude en preguntar si algo le molesta. Disculpas por la publicación de la sobre longitud.
- Las rutas son absolutas desde la raíz de un proyecto estándar de Maven. Una vez que haya adaptado las propiedades y / o los métodos de autenticación / recuperación de grupo en los SAM, puede compilar todos los archivos como WAR y desplegar este último en su AS tal como está para probarlo. La única dependencia es la de (
provided
)javaee-api
7.0 (más su controlador JDBC, a menos que ya esté presente en la ruta AS class). - Tuve que mover el código a un Gist debido a la restricción de longitud de publicación de SO.
- El
ServletContextListener
registra elAuthConfigProvider
. Guardar como/<project>/src/main/java/org/my/foosoft/authn/BigJaspicFactoryRegistrar.java
. -
AuthConfigProvider
. Guardar como/<project>/src/main/java/org/my/foosoft/authn/BigJaspicFactory.java
. - El
ServerAuthConfig
. Guardar como/<project>/src/main/java/org/my/foosoft/authn/LittleJaspicServerFactory.java
. - La clase de ayuda de implementación dual
ServerAuthContext
-ServerAuthModule
base. Esta es la parte 1/3 de la respuesta real. Guardar como/<project>/src/main/java/org/my/foosoft/authn/HttpServletSam.java
. - La implementación de SAM independiente . Respuesta real, parte 2/3. Guardar como
/<project>/src/main/java/org/my/foosoft/authn/StandaloneLdapSam.java
. - El JAAS LM-delegando SAM . Respuesta real, parte 3/3. Guardar como
/<project>/src/main/java/org/my/foosoft/authn/JaasDelegatingLdapSam.java
. - Conveniencia tipo de excepción . Guardar como
/<project>/src/main/java/org/my/foosoft/authn/JaspicMischief.java
. - Las
Properties
acompañantes. Adáptelos a sus necesidades si desea probar el código de autenticación real palabra por palabra. Guardar como/<project>/src/main/resources/org/my/foosoft/authn/jaspic-provider.properties
. - Acompañando la muestra
login.conf
snippet for (6); consulte la documentación del proveedor para conocer la ubicación real del sistema de archivos. -
/<project>/src/main/java/org/my/foosoft/presentation/UserUtils.java
(opcional - para fines de demostración: JSF foring bean ) -
/<project>/src/main/webapp/index.xhtml
(opcional - con fines de demostración: página de índice sin protección ) -
/<project>/src/main/webapp/login.xhtml
(opcional - para demostración: página de inicio de sesión ) -
/<project>/src/main/webapp/restricted/info.xhtml
(opcional - con fines de demostración: página de índice protegida para usuarios en el rolaccess_restricted_pages
) -
/<project>/src/main/webapp/WEB-INF/web.xml
(opcional - para fines de demostración y en aras de la completitud: módulo web DD )
Otras lecturas:
1 JASPIC es una SPI genérica, en teoría capaz de autenticar JMS, SAML-over-SOAP y cualquier otro tipo de mensaje, cuando se conecta a un tiempo de ejecución de procesamiento de mensajes capaz. Incluso su perfil de contenedor de servlets utilizado predominantemente no lo restringe excesivamente.
La naturaleza flexible y de bajo nivel de JASPIC implica el desconocimiento de la funcionalidad específica del protocolo, como la sesión HTTP. En consecuencia, ServerAuthContext
s / SAM se activan por el tiempo de ejecución para realizar la autenticación en cada solicitud.
Sin embargo, la especificación hace una provisión sobre esta deficiencia potencial al permitir que los SAM soliciten el inicio de una sesión de autenticación de contenedor por el tiempo de ejecución, a través de una propiedad de devolución de llamada de MessageInfo
. Cuando se solicita autenticación de solicitudes subsiguientes del mismo cliente, los SAM pueden evitar repetir todo el proceso, pidiendo al tiempo de ejecución que reutilice la sesión de autenticación AS previamente establecida, de ahí la identidad del usuario (llamante y / o Principal
(s) del grupo). Esto se logra mediante la ejecución del "do-nothing- / leave-authentication-state-as-is-protocol" que se muestra en el HttpServletSam
del código de muestra.
Por último, cabe señalar que ni el JASPIC ni la especificación Servlet definen claramente qué es una sesión de autenticación de contenedor . Para un usuario autenticado por SAM, para fines prácticos, consideraría la sesión de autenticación AS como el equivalente de la sesión HTTP, siempre y cuando a) la autenticación pertenezca a un contexto de aplicación única yb) el SAM, como se explicó anteriormente, señaliza la reutilización de la sesión de autenticación AS en cada solicitud.