Necesito un filtro que se llame antes de cada servlet y verifique si ese servlet tiene una anotación que indica que requiere autenticación, por ejemplo @ServletSecurity(@HttpConstraint(rolesAllowed={"user"})) en Servlet 3. Si eso no es así el caso, entonces el filtro simplemente regresará. Si el servlet requiere autenticación, verificará si el token de solicitud tiene un rol de user , si no lo tiene, establecerá automáticamente una respuesta NOT_AUTHENTICATED , sin siquiera pasar por el servlet.
Este trabajo debe realizarlo el filtro porque necesito validar el token JWT de la solicitud y agregar el JWT decodificado a la solicitud para que el servlet pueda usar su carga útil.
¿Cómo verifico las anotaciones de servlet de un filtro? En ese caso, ¿podría crear una anotación más simple como @RequiresAuth en el servlet? Porque no necesito roles en este proyecto.
¿Es posible devolver una respuesta no autenticada al cliente desde el filtro sin pasar por el servlet?
¿Es posible configurar el filtro para que sea el primero mediante programación?
Así es como lo resolví usando Jersey, pero necesito una solución solo con servlets:
@Priority(Priorities.AUTHENTICATION) public class AuthenticationFilter implements ContainerRequestFilter { @Context private ResourceInfo resourceInfo; @Override public void filter(ContainerRequestContext context) { final Method method = resourceInfo.getResourceMethod(); if (method.isAnnotationPresent(PermitAll.class)) return; if (method.isAnnotationPresent(DenyAll.class)) { context.abortWith(Response.status(Response.Status.FORBIDDEN).build()); return; } final RolesAllowed rolesAnnotation = method.getAnnotation(RolesAllowed.class); if (rolesAnnotation == null) return; } }¿Cómo verifico las anotaciones de servlet de un filtro? En ese caso, ¿podría crear una anotación más simple como @RequiresAuth en el servlet? Porque no necesito roles en este proyecto.
Es posible, pero no se recomienda. Los filtros están destinados a aplicarse selectivamente a los servlets que los necesitan. En su caso, solo lo asignaría a aquellos servlets que requieren autenticación.
En su ejemplo de Jersey, el AuthenticationFilter se aplica a todos los puntos finales. Con los filtros de servlet, usted decide a qué servlets/patrones de URL desea que se aplique este filtro. La introspección en busca de anotaciones ya no tiene sentido aquí.
¿Es posible devolver una respuesta no autenticada al cliente desde el filtro sin pasar por el servlet?
Sí. regresa del filtro llamando a response.setStatus(401) en lugar de chain.doFilter.
if (isAuthenticated()) { // this proceeds to the next filter or servlet in the chain chain.doFilter(request, response); } else { // this returns the response to the client response.setStatus(401); }¿Es posible configurar el filtro para que sea el primero mediante programación?
Sí. No es posible a través de anotaciones, pero sí a través de web.xml. Ahí está solo el orden de los elementos para cualquier servlet o patrón de URL dado.
<filter> <filter-name>filter1</filter-name> <filter-class>filter.Filter1</filter-class> </filter> <filter> <filter-name>filter2</filter-name> <filter-class>filter.Filter2</filter-class> </filter> <!-- filter2 will be applied 1st because it's listed 1st --> <filter-mapping> <filter-name>filter2</filter-name> <servlet-name>some-servlet</servlet-name> </filter-mapping> <!-- filter1 will be applied after filter2 --> <filter-mapping> <filter-name>filter1</filter-name> <servlet-name>some-servlet</servlet-name> </filter-mapping>