如何在 JSF 中实现登录过滤器? [英] How implement a login filter in JSF?

查看:20
本文介绍了如何在 JSF 中实现登录过滤器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

即使用户知道某些页面的网址,我也想阻止某些页面的访问.例如/localhost:8080/user/home.xhtml(需要先登录)如果没有登录则重定向到/index.xhtml.

I would like to block the access of some page even if the user knows the url of some pages. For example, /localhost:8080/user/home.xhtml (need to do the login first) if not logged then redirect to /index.xhtml.

在 JSF 中如何做到这一点?我在 Google 上读到需要过滤器,但我不知道该怎么做.

How do that in JSF ? I read in the Google that's needed a filter, but I don't know how to do that.

推荐答案

你需要实现javax.servlet.Filter 类,在 doFilter() 方法中完成所需的工作并将其映射到覆盖受限页面,/user/* 可能吗?在 doFilter() 中,您应该以某种方式检查会话中登录用户的存在.此外,您还需要考虑 JSF ajax 和资源请求.JSF ajax 请求需要特殊的 XML 响应才能让 JavaScript 执行重定向.需要跳过 JSF 资源请求,否则您的登录页面将不再有任何 CSS/JS/图像.

You need to implement the javax.servlet.Filter class, do the desired job in doFilter() method and map it on an URL pattern covering the restricted pages, /user/* maybe? Inside the doFilter() you should check the presence of the logged-in user in the session somehow. Further you also need to take JSF ajax and resource requests into account. JSF ajax requests require a special XML response to let JavaScript perform a redirect. JSF resource requests need to be skipped otherwise your login page won't have any CSS/JS/images anymore.

假设您有一个 /login.xhtml 页面,它通过 externalContext.getSessionMap().put("user", user),然后你可以通过 session.getAttribute("user") 获取它,如下所示:

Assuming that you've a /login.xhtml page which stores the logged-in user in a JSF managed bean via externalContext.getSessionMap().put("user", user), then you could get it via session.getAttribute("user") the usual way like below:

@WebFilter("/user/*")
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.
        }
    }


    // You need to override init() and destroy() as well, but they can be kept empty.
}

此外,过滤器还禁用了受保护页面上的浏览器缓存,因此浏览器后退按钮不会再显示它们.

Additionally, the filter also disabled browser cache on secured page, so the browser back button won't show up them anymore.

如果您碰巧使用 JSF 实用程序库 OmniFaces,上面的代码可以简化如下:

In case you happen to use JSF utility library OmniFaces, above code could be reduced as below:

@WebFilter("/user/*")
public class AuthorizationFilter extends HttpFilter {

    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response, HttpSession session, FilterChain chain) throws ServletException, IOException {
        String loginURL = request.getContextPath() + "/login.xhtml";

        boolean loggedIn = (session != null) && (session.getAttribute("user") != null);
        boolean loginRequest = request.getRequestURI().equals(loginURL);
        boolean resourceRequest = Servlets.isFacesResourceRequest(request);

        if (loggedIn || loginRequest || resourceRequest) {
            if (!resourceRequest) { // Prevent browser from caching restricted resources. See also https://stackoverflow.com/q/4194207/157882
                Servlets.setNoCacheHeaders(response);
            }

            chain.doFilter(request, response); // So, just continue request.
        }
        else {
            Servlets.facesRedirect(request, response, loginURL);
        }
    }

}

另见:

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆