我正在使用JSF2。我已经实现了一个自定义面部servlet:
public class MyFacesServletWrapper extends MyFacesServlet {
// ...
}
其中我正在进行一些授权检查并在用户未登录时发送重定向:
public void service(ServletRequest request, ServletResponse response) {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
if (...) {
String loginURL = req.getContextPath() + "/LoginPage.faces";
res.sendRedirect(loginURL);
}
}
当用户尝试导航到其他页面时,此方法有效。但是,当JSF命令链接/按钮提交JSF表单时,这不起作用。行sendRedirect()
行被命中并执行,没有抛出异常,但用户停留在同一页面。基本上,根本没有视觉变化。
为什么这适用于页面导航,而不适用于表单提交?
答案 0 :(得分:17)
您的具体问题很可能是因为您的JSF命令链接/按钮实际上发送了一个ajax请求,而该请求又需要特殊的XML响应。如果您要发送重定向作为对ajax请求的响应,那么它只会将ajax请求重新发送到该URL。如果没有反馈,这反过来会失败,因为重定向URL返回整个HTML页面而不是特殊的XML响应。您应该实际返回一个特殊的XML响应,其中已指示JSF ajax引擎更改当前window.location
。
但实际上你遇到了更大的问题:使用错误的工具来完成工作。您应该使用servlet filter作为工作,而不是本地的servlet,并且肯定不会取代负责所有JSF工作的FacesServlet
。
假设您正在请求/视图作用域的JSF支持bean中执行登录,如下所示(如果您正在使用容器管理的身份验证,请参阅Performing user authentication in Java EE / JSF using j_security_check的第二个示例):
externalContext.getSessionMap().put("user", user);
然后这个过滤器的启动示例应该:
@WebFilter("/*") // Or @WebFilter(servletNames={"facesServlet"})
public class AuthorizationFilter implements Filter {
private static final String AJAX_REDIRECT_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<partial-response><redirect url=\"%s\"></redirect></partial-response>";
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
String loginURL = request.getContextPath() + "/login.xhtml";
boolean loggedIn = (session != null) && (session.getAttribute("user") != null);
boolean loginRequest = request.getRequestURI().equals(loginURL);
boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER + "/");
boolean ajaxRequest = "partial/ajax".equals(request.getHeader("Faces-Request"));
if (loggedIn || loginRequest || resourceRequest)) {
if (!resourceRequest) { // Prevent browser from caching restricted resources. See also https://stackoverflow.com/q/4194207/157882
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.
}
chain.doFilter(request, response); // So, just continue request.
}
else if (ajaxRequest) {
response.setContentType("text/xml");
response.setCharacterEncoding("UTF-8");
response.getWriter().printf(AJAX_REDIRECT_XML, loginURL); // So, return special XML response instructing JSF ajax to send a redirect.
}
else {
response.sendRedirect(loginURL); // So, just perform standard synchronous redirect.
}
}
// ...
}
答案 1 :(得分:0)
FacesContext.getCurrentInstance()getExternalContext()重定向( “newpage.xhtml”);试试这个....代替res.sendredirect(cpath)。