Есть ли простой способ предварительной обработки и перенаправления запросов GET?
Я ищу ответ наилучшей практики. Я хочу сделать некоторую предварительную обработку для запросов GET. Например, если пользователю не разрешено просматривать страницу, перенаправьте его на другую страницу. Но я не хочу использовать обычный фильтр сервлетов, потому что я хотел бы выразить это поведение в faces-config.xml
, Возможно ли это и как это называется, как это можно сделать?
Могу ли я определить какой-то боб фильтра, который также возвращает строку, сообщающую faces-config.xml
куда идти дальше?
Я за это погуглил, но ударил только по обычным фильтрам. Если я использую фильтры, могу ли @WebFilter
быть @ManagedBean
в то же время? Или это плохой стиль?
1 ответ
Если вы используете домашнюю аутентификацию HTTP-запроса поверх JSF, тогда фильтр сервлетов - действительно лучший подход. JSF является "просто" инфраструктурой MVC, и в API JSF ничего не было указано для фильтрации входящих HTTP-запросов для проверки аутентификации пользователя. На обычных GET-запросах управляемый JSF-компонент обычно создается только тогда, когда HTTP-ответ собирается быть создан и отправлен или, возможно, уже зафиксирован. Это не контролируется изнутри управляемого компонента. Если ответ уже зафиксирован, вы больше не сможете его изменить (перенаправить). Аутентификация и изменение запроса / ответа действительно должны быть сделаны задолго до того, как ответ собирается быть отправленным.
Если бы вы не использовали аутентификацию homegrowing, вы могли бы использовать для этого управляемую контейнером аутентификацию Java EE, которая должна быть объявлена <security-constraint>
записи в web.xml
, Обратите внимание, что это также не связано с JSF, но, по крайней мере, избавляет вас от создания фильтра сервлетов и управляемого компонента.
Общий подход заключается в группировке ограниченных страниц за определенным шаблоном URL, например /app/*
, /private/*
, /secured/*
и т. д. и воспользоваться тем, что JSF хранит бины сессий в области видимости как HttpSession
атрибутов. Представьте, что у вас есть управляемый компонент JSF-сессии UserManager
который содержит вошедшего в систему пользователя, то вы можете проверить это следующим образом:
@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.
}
}
// ...
}
Если вы используете JSF 2.2+, есть другой способ контролировать ответ прямо перед его отправкой. Вы можете использовать <f:viewAction>
, Поместите следующее где-то на ваш взгляд:
<f:metadata>
<f:viewAction action="#{authenticator.check}" />
</f:metadata>
с
@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";
}
}
// ...
}
Это гарантированно сработает до того, как ответ будет предоставлен. В противном случае, когда вы делаете работу, например, в @PostConstruct
тогда вы можете рискнуть java.lang.IllegalStateException: response already committed
когда компонент создается в первый раз, когда ответ уже частично обработан (и зафиксирован).
Я только не считаю это "лучшей" практикой, когда речь идет об обработке HTTP-аутентификации. Это делает его слишком тесно связанным с JSF. Вы действительно должны использовать фильтр сервлетов. Но для других целей это может быть хорошо.