ajax - example - Autenticación REST para Java EE
f:ajax listener (2)
En mi experiencia, es difícil implementar un sistema que use el servicio de autenticación y autorización Java EE que funcionaría para ambos servicios REST y MVC del lado del servidor como JSP o JSF al mismo tiempo. Toda mi experiencia se inclina hacia el uso de la autenticación basada en formularios para la parte MVC y algún tipo de autenticación de token (OAuth, Kerberos, LTPA) para los servicios REST. El uso de la autenticación de Formulario o Básica para los servicios REST fue generalmente un desafío de implementación, aunque lo hicimos y funciona bien en dos proyectos.
También depende de la implementación del servidor preferido.
He pasado algo de tiempo evaluando las opciones disponibles para autenticar de forma tranquila a un usuario en una aplicación Java EE .
Por lo tanto, sugiera si las opciones enumeradas a continuación son válidas junto con las declaraciones sobre ventajas o desventajas. Puede ser que me falten detalles que puedan hacer viable un método de autenticación. O puede ser que haya otra opción que no he tenido en cuenta (de nuevo, estamos hablando estrictamente de Java EE, por lo que no hay autenticación de consulta y, a menos que se pueda hacer de una manera compatible con EE)
1. Autenticación DIGEST / BASIC
<security-constraint>
<web-resource-collection>
<web-resource-name>admin</web-resource-name>
<url-pattern>/protected/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>DIGEST/BASIC</auth-method>
<realm-name>as-defined-secuity-realm</realm-name>
</login-config>
Ventajas
Esta es una forma amigable de autenticación de REST. Puede enviar las credenciales de autorización a través de una llamada AJAX. Una vez que el usuario esté autenticado, el navegador acompañará cualquier solicitud con la
Authorization: Basic/Digest QWxhZGRpbjpvcGVuIHNlc2FtZQ==
adecuadaAuthorization: Basic/Digest QWxhZGRpbjpvcGVuIHNlc2FtZQ==
header. En caso de malas credenciales, al usuario se le presentará la pantalla de inicio de sesión del navegador feo; si puede vivir con eso, entonces la autenticación BÁSICA / DIGITAL es la forma para usted.En el caso de Digest, la cadena pasada al servidor es una cadena encriptada MD5, que es definitivamente más segura que la Básica (que es una codificación Base64 de la cadena ''usuario: contraseña''), pero sin embargo es decipherable . Entonces, en términos de seguridad, BASIC es prácticamente tan seguro como la autenticación FORM y DIGEST es el más seguro de todos. En conclusión, si su sitio es enteramente HTTPS (me refiero completamente a que, si algunos recursos se obtienen a través de HTTP, sus encabezados de autorización, por ejemplo, serán visibles para un tercero), es seguro que vaya con BASIC / DIGEST.
- Fácil de configurar.
Desventajas
- Desconectarse es difícil de implementar. Consulte here y here Seguro que tiene una buena solicitud de AJAX que autentica al usuario, pero también necesita tener un? AJAX? solicitud que cierra la sesión del usuario (lo que hace que aparezca nuevamente la ventana de inicio de sesión del navegador) Por cierto, el método nice servlet 3.0 request.logout () no funciona correctamente en este caso .
- Los tiempos de espera de sesión son muy difíciles de implementar. La caducidad de la sesión ocurre (es el trabajo del contenedor de servlets), pero el navegador enviará los encabezados de autorización en la siguiente solicitud, lo que provocará una nueva autenticación.
- No hay página de inicio de sesión personalizada. Ninguna.
- Es difícil hacer un seguimiento de las sesiones autenticadas.
2. FORMACIÓN basada en la autenticación
<security-constraint>
<web-resource-collection>
<web-resource-name>admin</web-resource-name>
<url-pattern>/protected/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>as-defined-security-realm</realm-name>
<form-login-config>
<form-login-page>/auth/login.html</form-login-page>
<form-error-page>/auth/error.html</form-error-page>
</form-login-config>
</login-config>
En pocas palabras, si el usuario accede a una url protected/*
, la página de inicio de sesión se incluye en la respuesta. Entonces, en lugar del contenido que el usuario espera, obtendrá la página de inicio de sesión configurada en la etiqueta de form-login-page
. Si la contraseña es correcta, se reenviará (302 Paginado movido permanentemente) al url protected/*
solicitado inicialmente. Si la contraseña es NOK, el usuario será reenviado (302 Paginado movido permanentemente) a la página de error.
Ventajas
- Página de inicio de sesión personalizada: esta parece ser la más popular :)
- Cerrar sesión es fácil de implementar. Solo se necesita invalidar la HttpSession o llamar al método request.logout () (Servlet 3.0).
- Tiempos de espera de sesión
- SI y SOLO si acepta tener una página separada para iniciar sesión, esta es la solución para usted.
Desventajas
- RESTO hostil (no voy a profundizar en la filosofía del descanso y mantener el estado del lado del servidor no es un debate REST. Estamos analizando la autenticación REST de una manera JAVA EE y el estado del lado del servidor siempre se mantiene para cualquier sujeto autenticado) . Lo que es realmente malo de usar la autenticación FORM es el hecho de que uno no puede tener un comportamiento consistente en los navegadores. Y todo se debe a la redirección 302 que manejan algunos navegadores en las funciones de respuesta AJAX, mientras que otros redirigen toda la página (cambiar la URL en la barra de navegación). Más detalles here y here . ¡No puede evitar ese redireccionamiento 302, por lo que no hay autenticación FORM y REST para su señor!
3. Autenticación programática.
Configurar una URL para la autenticación. Detrás de esa URL puede tener un servlet que crea una instancia de un módulo de inicio de sesión (forma JAAS) y llama al método HttpServletRequest.login (usuario, pase) junto con las credenciales. Debe generar una respuesta 401/403 si falla el inicio de sesión.
Puede implementarlo simplemente especificando las restricciones de seguridad en su web.xml:
<security-constraint>
<web-resource-collection>
<web-resource-name>admin</web-resource-name>
<url-pattern>/protected/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
En el lado del servidor, simplemente necesita configurar un servicio RESTFul que autentique a la persona que llama. Aquí hay un código de ejemplo:
@Path("/auth")
@ApplicationPath("/rest")
public class AuthenticationRestFacade {
@POST
@Path("/login")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public User login(User loginInfo, @Context HttpServletRequest request) throws LoginException, ServletException {
// nasty work-around for Catalina AuthenticatorBase to be able to
// change/create the session cookie
request.getSession();
request.login(loginInfo.getName(), loginInfo.getPassword());
Ventajas
- Página de inicio de sesión personalizada.
- Compatible con AJAX / REST
- URL de cierre de sesión (si una URL está configurada para hacerlo)
- Tiempos de espera de sesión (contenedor administrado)
- Puede devolver los datos de inicio de sesión (nombre de usuario, correo electrónico, roles, grupos, etc.) en la respuesta (realmente agradable porque no tiene que hacer otra llamada después de un inicio de sesión exitoso)
Desventajas
- Necesita un poco de escritura de código.
- Necesita que la aplicación pueda manejar las respuestas 401/403 y mostrar la ventana de inicio de sesión
Para concluir, las mejores opciones viables:
- Si no te importan los tiempos de espera de sesión o los cierres de sesión -> DIGEST
- Si lo anterior no funciona para usted Y no necesita tener una página de inicio de sesión incrustada (o una página similar a un panel modal) y está bien con una sola página para la autenticación -> FORMULARIO
- Si lo anterior no funciona para usted y desea que toda la flexibilidad y la compatibilidad en el mundo vaya con el enfoque de PROGRAMMATIC. Debe definir la URL de inicio de sesión / cierre de sesión y también el código de su cliente debe poder hacer frente a las respuestas 401/403 (no es fácil).
Estoy deseando que ustedes sugieran algunas soluciones alternativas viables. Porque ahora mismo odiaría ir con el enfoque de PROGRAMMATIC.
Probablemente discutible si estos son RESTful, pero sería bueno al menos abordar lo siguiente:
¿Qué pasa con los keberos ? Usando un servidor de autenticación como Windows AD ...
¿Qué pasa con los certificados de clave pública ? Confiando en los certificados proporcionados por el cliente para identificar a un usuario ...
¿Qué pasa con Tokens ? Emisores de tokens de terceros, como OpenID ...