我正在寻找最佳实践答案。我想为GET请求做一些预处理。所以例如如果不允许用户查看该页面,请将其重定向到另一页面。但我不想使用普通的servlet过滤器,因为我想在faces-config.xml
中表达这种行为。这是可能的,如何调用,怎么做?
我可以定义一些也会返回一个String的Filter bean,告诉faces-config.xml
下一步去哪里吗?
我用谷歌搜索了这个,但只打了正常的过滤器。如果我使用过滤器,@WebFilter
可以同时成为@ManagedBean
吗?还是那种糟糕的风格?
答案 0 :(得分:18)
如果您在JSF之上进行HTTP请求身份验证,那么servlet过滤器确实是最好的方法。 JSF“只是”一个MVC框架,并且未指定JSF API中的任何内容来过滤传入的HTTP请求以检查用户身份验证。在正常的GET请求中,JSF托管bean通常仅在即将创建和发送HTTP响应时构建,或者可能已经提交。这不受托管bean内部的控制。如果响应已经提交,您将无法再更改(重定向)它。在即将发送响应之前,确实需要进行身份验证和更改请求/响应。
如果您不是homegrowing身份验证,那么您可以使用Java EE提供的容器管理身份验证,这将由<security-constraint>
中的web.xml
条目声明。请注意,这也与JSF分离,但它至少可以使您免于在家中生成servlet过滤器和托管bean。
一般方法是将受限制的页面分组为某个URL模式(如/app/*
,/private/*
,/secured/*
等),并利用JSF存储会话范围的事实bean为HttpSession
属性。想象一下,你有一个JSF会话作用域托管bean 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
,那么当响应已经部分呈现(并已提交)时,第一次创建bean时,您可能会冒java.lang.IllegalStateException: response already committed
的风险。
在处理HTTP身份验证时,我不会认为它是一种“最佳”做法。它使它与JSF结合得太紧。你应该继续使用servlet过滤器。但出于其他目的,它可能没问题。