JavaRush /Blog Java /Random-ES /JAAS - Introducción a la tecnología (Parte 2)
Viacheslav
Nivel 3

JAAS - Introducción a la tecnología (Parte 2)

Publicado en el grupo Random-ES
Continuación de la primera parte del artículo sobre JAAS. Averigüemos si es posible utilizar solo anotaciones para JAAS y qué problemas encontraremos. Aprenderemos en esta parte qué herramientas API de Servlet nos permiten hacer que el código sea más universal. Y resumamos lo que leemos.
JAAS - Introducción a la tecnología (Parte 2) - 1

Continuación

En la primera parte de la revisión de la tecnología JAAS (ver " JAAS - Introducción a la tecnología (Parte 1) "), analizamos el caso de uso principal de JAAS y la API de Servlet. Vimos que el contenedor de servlets Tomcat gestionaba la seguridad de nuestra aplicación web utilizando la arquitectura JAAS. Al tener conocimiento del "método de autenticación" y del "reino de seguridad", el contenedor Tomcat nos proporcionó la implementación necesaria del mecanismo de autenticación y nos proporcionó el CallbackHandler, simplemente lo usamos todo en nuestro módulo de inicio de sesión. Lo único importante que debe recordar es que el navegador guarda los datos de inicio de sesión y contraseña transmitidos mediante la autenticación BÁSICA. Por lo tanto, para cada nuevo escaneo usando Chrome, puede presionar Ctrl+Shift+N para abrir una nueva ventana para trabajar en modo incógnito.
JAAS - Introducción a la tecnología (Parte 2) - 2

Anotaciones

La configuración mediante XML hace tiempo que pasó de moda. Por lo tanto, es importante decir que a partir de la versión 3.0 de Servlet API, tenemos la oportunidad de establecer la configuración del servlet mediante anotaciones, sin utilizar el archivo descriptor de implementación web.xml. Veamos cómo cambiará la gestión de la seguridad si utilizamos anotaciones. ¿Y es posible implementar los enfoques descritos anteriormente utilizando anotaciones? La especificación API de Servlet y su sección " Anotaciones y capacidad de conexión " nos ayudarán nuevamente a comprender las anotaciones . Esta sección dice que una declaración de servlet web.xmlse puede reemplazar por una anotación @WebServlet. En consecuencia, nuestro servlet se verá así:
@WebServlet(name="app", urlPatterns = "/secret")
public class App extends HttpServlet {
A continuación, veamos el capítulo " 13.3 Seguridad programática ". Dice que también podemos declarar una Restricción de Seguridad mediante anotaciones:
@WebServlet(name="app", urlPatterns = "/secret")
@ServletSecurity(httpMethodConstraints = {
        @HttpMethodConstraint(value = "GET", rolesAllowed = "admin")
})
public class App extends HttpServlet {
Ahora web.xmlsolo queda un bloque en el nuestro: login-config. El problema es que resulta que no hay manera de reemplazarlo fácil y simplemente. Debido a la estrecha conexión entre la configuración de seguridad de la aplicación web y la configuración de seguridad del servidor web, no existe una forma sencilla y universal de hacerlo, ni siquiera mediante programación. Este es uno de los problemas con la autenticación mediante JAAS y Servlet API. Hablando de bloque login-config, vale la pena entender que es una descripción declarativa de los mecanismos de autenticación, es decir. Mecanismos de autenticación. Todavía no existe una forma universal sencilla de reemplazarlo, porque... El procesamiento web.xmlocurre en lo profundo de los contenedores de servlets. Por ejemplo, en Tomcat puedes mirar la fuente ContextConfig.java . Por lo tanto, incluso para el contenedor de servlets Tomcat existen varias opciones y todas son diferentes. Por ejemplo, si utilizamos el contenedor de servlets Embedded Tomcat (es decir, creamos un servidor web a partir de código), puede leer sobre dichas opciones aquí: " Embedded Tomcat con autenticación básica mediante código ". Además, se puede ver un ejemplo general de cómo generar Embedde Tomcat en la guía de la plataforma Heroku PaaS: “ Crear una aplicación web Java usando Embedded Tomcat ”. Si Tomcat no se usa en modo integrado, entonces para Tomcat puede usar un enfoque comúnmente usado: detectores de eventos. En Tomcat, esto es " El componente de escucha de LifeCycle ". Al mismo tiempo, es importante comprender que los contenedores de servlets (en nuestro caso, Tomcat) pueden tener sus propios cargadores de clases y no será posible simplemente tomar y usar sus clases. Para Tomcat es necesario comprender el " CÓMO HACER el cargador de clases ". En otro contenedor de servlets llamado Undertow, esto se puede lograr usando " Extensiones de servlet ". Como puede verse, algunos han previsto mecanismos más flexibles, mientras que otros no. Como puedes ver, no existe una única opción. Todos son muy diferentes. ¿Es posible de alguna manera hacer algo universal solo con Servlet API y JAAS? En Internet puede encontrar una propuesta para utilizar Servlet Filter para realizar la autenticación sin bloqueo login-config. Finalmente consideremos esta opción. Esto nos permitirá repetir cómo funciona JAAS.
JAAS - Introducción a la tecnología (Parte 2) - 3

Filtro de autenticación

Entonces, nuestro objetivo es deshacernos del web.xmlarchivo por completo. Si nos deshacemos de él, lamentablemente ya no podremos utilizar la restricción de seguridad, porque su procesamiento puede ocurrir mucho antes de que se apliquen los filtros de servlet. Esta es la tarifa que debes pagar por la “versatilidad” de usar filtros. Aquellos. Tendremos que eliminar la anotación @ServletSecurityy todas las comprobaciones que describimos anteriormente en la restricción de seguridad deberán realizarse mediante programación. Como puede ver, esta opción también nos impone muchas restricciones desagradables. En primer lugar, eliminemos la anotación @ServletSecuritydel recurso y el bloque login-configdel archivo web.xml. Ahora, nosotros mismos tendremos que implementar la autenticación básica. Ahora agreguemos nuestro filtro:
@WebFilter("/*")
public class JaasFilter implements javax.servlet.Filter {
Hasta aquí parece sencillo. Escribamos un método de inicialización:
@Override
public void init(FilterConfig filterConfig) throws ServletException {
	String jaas_conf = filterConfig.getServletContext().getRealPath("/WEB-INF/jaas.config");
	System.getProperties().setProperty("java.security.auth.login.config",jaas_conf);
}
Como puede ver, ahora nos vemos obligados a utilizar herramientas JAAS básicas para buscar el archivo de configuración jaas. Esto tiene un gran inconveniente: si hay varias aplicaciones, una aplicación puede violar la autenticación de otra. La forma general de configurar un archivo de configuración Jaas se describe en detalle en la documentación de JAAS: " Apéndice A: Configuración de JAAS en el archivo de propiedades de seguridad java.security ". A continuación, describiremos el método de filtrado en sí. Comencemos recibiendo una solicitud HTTP:
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
	HttpServletRequest req = (HttpServletRequest) request;
	// Если в реквесте уже есть Principal - ничего не делаем
	if (req.getUserPrincipal() != null ) {
		chain.doFilter(request, response);
	}
Aquí todo es sencillo. Si Principal está disponible, la autenticación se realiza correctamente. A continuación, debe describir las acciones del filtro cuando el usuario no ha pasado la autenticación, es decir aún no ha sido reconocido. Anteriormente describimos el método de autenticación básico, BÁSICO. Porque Dado que ahora estamos escribiendo el filtro nosotros mismos, tendremos que descubrir cómo funciona realmente la autenticación BÁSICA. Puede utilizar " Documentos web de MDN: autorización HTTP ". Y también "¿ Cómo funciona la autenticación HTTP? " De la descripción de cómo funciona la autenticación básica, queda claro que si el servidor desea realizar la autenticación BÁSICA y el usuario no ha proporcionado datos, entonces el servidor envía un encabezado especial "WWW-Authenticate" y el código de error 401. Creemos un método interno para esto:
private void requestNewAuthInResponse(ServletResponse response) throws IOException {
	HttpServletResponse resp = (HttpServletResponse) response;
	String value = "Basic realm=\"JaasLogin\"";
	resp.setHeader("WWW-Authenticate", value);
	resp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
Ahora usemos este método y agreguemos doFilterel siguiente bloque de código al método:
// Получаем security Header. А если его нет - запрашиваем
String secHeader = req.getHeader("authorization");
if (secHeader == null) {
	requestNewAuthInResponse(response);
}
Ahora agreguemos una rama para if, que se ejecutará cuando el encabezado ya haya sido transmitido:
// Проверяем аутентификацию
else {
	String authorization = secHeader.replace("Basic ", "");
	Base64.Decoder decoder = java.util.Base64.getDecoder();
	authorization = new String(decoder.decode(authorization));
	String[] loginData = authorization.split(":");
	try {
		if (loginData.length == 2) {
			req.login(loginData[0], loginData[1]);
			chain.doFilter(request, response);
		} else {
			requestNewAuthInResponse(response);
		}
	} catch (ServletException e) {
		requestNewAuthInResponse(response);
	}
}
Puede agregar autorización a este código, por ejemplo: req.isUserInRole("admin") Hemos realizado la autenticación con usted mediante un filtro. Por un lado, hay mucho código y procesamiento manual. Por otro lado, está la versatilidad y la independencia del servidor.
JAAS - Introducción a la tecnología (Parte 2) - 4

Conclusión

Ahora hemos llegado al final de esta revisión. Espero que ahora quede un poco más claro qué es JAAS, qué es una Materia y qué son los Principales. Las palabras Security Realm y Login Config ya no generarán preguntas. Además, ahora sabemos cómo utilizar JAAS y la API de Servlet juntos. Además, aprendimos sobre los cuellos de botella donde las anotaciones en la API de Servlet no nos salvarán. Por supuesto, esto no es todo. Por ejemplo, la autenticación en Java puede no ser sólo BÁSICA. Puede ver otros tipos en la especificación API de Servlet en la sección " 13.6 Autenticación ". Es difícil encontrar información detallada sobre JAAS en Internet. Pero puedo recomendar este material: Espero que la información de esta revisión sea útil y comprensible. #viacheslav
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION