JEECMS重定向到登陆页面

April 27, 2013

需求:把所有未登陆的请求重定向到登陆页面

用Handler Interceptor验证登陆

JEECMS的FrontContextInterceptor已经实现了判断用户是否登陆的逻辑,只要在这基础上加上重定向就可以了。

修改FrontContextInterceptor.java:

if (user != null) {
    CmsUtils.setUser(request, user);
} else if (!isAllowed(request)) {
    response.sendRedirect(request.getContextPath() + site.getLoginUrl());
    return false;
}

isAllowed方法用于判断是否允于未登录时直接访问:

private boolean isAllowed(HttpServletRequest request)
	    throws ServletException {
    String[] allowedUrl = {"login.jspx"};
    String  requestURI  = request.getRequestURI();

    if (!request.getMethod().equals("GET")) {
       	return true;
    }

    for (int i = 0; i < allowedUrl.length; i++) {
       	if (requestURI.indexOf(allowedUrl[i]) != -1) {
            return true;
    	}
    }
    return false;
}

用Filter验证登陆

对静态页面,FrontContextInterceptor是不会处理的,所以再实现一个filter来处理。

web.xml:

<filter>
    <filter-name>authFilter</filter-name>
    <filter-class>com.jeecms.common.web.AuthFilter</filter-class>
</filter>

要过滤*.jhtml, *.html, *.htm的请求,加上AuthFilter,例如

<filter-mapping>
    <filter-name>authFilter</filter-name>
    <url-pattern>*.jhtml</url-pattern>
</filter-mapping>

AuthFilter.java:

public void doFilter(ServletRequest req,
			ServletResponse rep, FilterChain chain)
		throws ServletException, IOException {

	HttpServletRequest request = (HttpServletRequest) req;
	HttpServletResponse response = (HttpServletResponse) rep;

	ServletContext sc = config.getServletContext();
	ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(sc);

	CmsUserMng cmsUserMng = (CmsUserMng)context.getBean("cmsUserMng");
	AuthenticationMng authMng = (AuthenticationMng)context.getBean("authenticationMng");

	CmsUser user = null;
	Integer userId = authMng.retrieveUserIdFromSession(session, request);
	if (userId != null) {
        user = cmsUserMng.findById(userId);
   	}

	if (user == null && (!isAllowed(request)))  {
        response.sendRedirect(request.getContextPath() + "/login.jspx");
	} else {
        chain.doFilter(req, rep);
	}
}

主体参考FrontContextInterceptor, 因为在web.xml配置filter, 所以在AuthFilter直接用WebApplicationContextUtil拿到ApplicationContex, 再拿到判断登用用的AuthenticationMng,CmsUserMng

简化

像上面这样分开处理动态和静态页面略麻烦,而且验证也做多了,其实我们不需要在AuthFilter里拿到用户的。所以我们简化一下逻辑,把全部页面都用一个AuthFilter过滤。

public class AuthFilter implements Filter {

    public void doFilter(ServletRequest req,
			 ServletResponse rep, FilterChain chain)
	    throws ServletException, IOException {

	// We need HttpServlet* to get access to work with HTTP
	// .....
	// Obtain beans from Spring
	// ....

	if (!isLogined(session, authMng) && !isAllowed(request, response)) {
	    response.sendRedirect(request.getContextPath() + "/login.jspx");
	} else {
	    chain.doFilter(req, rep);
	}
    }

    // Check if an user is logined
    private isLogined(SessionProvider session, AuthenticationMng authMng) {
	String authId = (String) session.getAttribute(request, AUTH_KEY);
	if (authId == null || authMng.retrieve(authId) == null) {
	    return false;
	}
	return true;
    }

    // Check if a request is allowed even if no user are logined
    private boolean isAllowed( //...
}