jsf - faces - ¿Hay alguna manera fácil de preprocesar y redirigir las solicitudes GET?
primefaces servlet (1)
Estoy buscando una respuesta de mejores prácticas. Quiero hacer un preprocesamiento para las solicitudes GET. Entonces, por ejemplo, si el usuario no puede ver la página, rediríjala a otra página. Pero no quiero usar el filtro de servlet normal, porque me gustaría expresar este comportamiento en faces-config.xml
. ¿Es esto posible y cómo se llama, cómo se puede hacer?
¿Puedo definir algún Bean Filter que también devuelva un String que diga a faces-config.xml
dónde ir después?
Busqué en Google esto, pero solo acerté en los filtros normales. Si uso filtros, ¿un @WebFilter
puede ser @WebFilter
al mismo tiempo? ¿O es ese mal estilo?
Si está haciendo crecer la autenticación de solicitud HTTP sobre JSF, entonces un filtro de servlet es realmente el mejor enfoque. JSF es "solo" un marco MVC y no se especifica nada en la API JSF para filtrar las solicitudes HTTP entrantes para verificar la autenticación del usuario. En las solicitudes GET normales, un bean gestionado JSF normalmente solo se genera cuando la respuesta HTTP está a punto de crearse y enviarse, o tal vez ya se ha confirmado. Esto no es controlable desde dentro del bean administrado. Si la respuesta ya se ha confirmado, ya no podrá cambiarla (redirigirla). La autenticación y el cambio de la solicitud / respuesta realmente deben hacerse mucho antes de que la respuesta esté a punto de enviarse.
Si no fuera la autenticación casera, entonces podría haber usado la autenticación administrada por contenedor proporcionada por Java EE para esto, que debe ser declarada por <security-constraint>
entradas <security-constraint>
en web.xml
. Tenga en cuenta que esto también está desacoplado de JSF, pero al menos le ahorra a homegrowing un filtro de servlet y un bean administrado.
El enfoque general es agrupar las páginas restringidas detrás de un determinado patrón de URL como /app/*
, /private/*
, /secured/*
, etc. y aprovechar la ventaja de que JSF almacena beans de ámbito de sesión como atributos HttpSession
. Imagínese que tiene un UserManager
bean administrado de sesión administrada de UserManager
que contiene el usuario conectado, luego puede verificarlo de la siguiente manera:
@WebFilter(urlPatterns={"/app/*"})
public class AuthenticationFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
UserManager userManager = (session != null) ? (UserManager) session.getAttribute("userManager") : null;
if (userManager == null || !userManager.isLoggedIn()) {
response.sendRedirect(request.getContextPath() + "/login.xhtml"); // No logged-in user found, so redirect to login page.
} else {
chain.doFilter(req, res); // Logged-in user found, so just continue request.
}
}
// ...
}
Si está utilizando JSF 2.2+, hay otra forma de controlar la respuesta justo antes de que se envíe. Puede hacer uso de <f:viewAction>
. Pon lo siguiente en alguna parte de tu vista:
<f:metadata>
<f:viewAction action="#{authenticator.check}" />
</f:metadata>
con
@Named
@RequestScoped // Scope doesn''t matter actually. The listener will always be called on every request.
public class Authenticator {
public String check() {
if (authenticated) {
return null;
}
else {
return "login?faces-redirect=true";
}
}
// ...
}
Esto está garantizado para ser disparado antes de que la respuesta sea renderizada. De lo contrario, cuando haces el trabajo en, por ejemplo, @PostConstruct
, puedes arriesgarte a java.lang.IllegalStateException: response already committed
cuando el bean se crea por primera vez cuando la respuesta ya se ha procesado (y confirmado).
Solo no lo consideraría una "mejor" práctica cuando se trata de manejar la autenticación HTTP. Lo hace muy apretado acoplado a JSF. Deberías seguir usando un filtro de servlet. Pero para otros fines, puede estar bien.