openfire 拦截servlet请求代码解析

下面的内容以获取用户状态插件的类(PresenceStatusServlet)为例子说明

@Override
public void init(ServletConfig servletConfig) throws ServletException {
	super.init(servletConfig);
	plugin =(PresencePlugin) XMPPServer.getInstance().getPluginManager().getPlugin("presence");
	xmlProvider = new XMLPresenceProvider();
	imageProvider = new ImagePresenceProvider(this);
	textProvider = new TextPresenceProvider();
	available = loadResource("/images/user-green-16x16.gif");
	away = loadResource("/images/user-yellow-16x16.gif");
	chat = loadResource("/images/user-green-16x16.gif");
	dnd = loadResource("/images/user-red-16x16.gif");
	offline = loadResource("/images/user-clear-16x16.gif");
	xa = loadResource("/images/user-yellow-16x16.gif");
	// Exclude this servlet from requering the user to login
	//不包括下面这个servlet请求,即下面这个请求不会被拦截
	AuthCheckFilter.addExclude("presence/status");
}
package org.jivesoftware.admin;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.Set;
import java.util.StringTokenizer;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jivesoftware.util.ConcurrentHashSet;
import org.jivesoftware.util.WebManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A simple filter which checks for the auth token in the user's session. If it's not there
 * the filter will redirect to the login page.
 */
public class AuthCheckFilter implements Filter {

	private static final Logger Log = LoggerFactory.getLogger(AuthCheckFilter.class);
//excludes是过滤器不需要认证的路径,将其缓存起来,实现动态的添加和删除
    private static Set<String> excludes = new ConcurrentHashSet<String>();

    private ServletContext context;
    private String defaultLoginPage;

    //动态添加额外不需要认证的路径
    public static void addExclude(String exclude) {
        excludes.add(exclude);
    }

	//动态删除不需要认证的路径
    public static void removeExclude(String exclude) {
        excludes.remove(exclude);
    }

    /**
     * Returns true if a URL passes an exclude rule.
     *
     * @param url the URL to test.
     * @param exclude the exclude rule.
     * @return true if the URL passes the exclude test.
     */
    public static boolean testURLPassesExclude(String url, String exclude) {
        // If the exclude rule includes a "?" character, the url must exactly match the exclude rule.
        // If the exclude rule does not contain the "?" character, we chop off everything starting at the first "?"
        // in the URL and then the resulting url must exactly match the exclude rule. If the exclude ends with a "*"
        // character then the URL is allowed if it exactly matches everything before the * and there are no ".."
        // characters after the "*". All data in the URL before
        // the "@" character is chopped.

        if (url.contains("@")) {
            url = url.substring(url.indexOf("@"));
        }

        if (exclude.endsWith("*")) {
            if (url.startsWith(exclude.substring(0, exclude.length()-1))) {
                // Now make sure that there are no ".." characters in the rest of the URL.
                if (!url.contains("..") && !url.toLowerCase().contains("%2e")) {
                    return true;
                }
            }
        }
        else if (exclude.contains("?")) {
            if (url.equals(exclude)) {
                return true;
            }
        }
        else {
            int paramIndex = url.indexOf("?");
            if (paramIndex != -1) {
                url = url.substring(0, paramIndex);
            }
            if (url.equals(exclude)) {
                return true;
            }
        }
        return false;
    }

	//从配置文件(OpenFire/src/web/WEB-INF/web.xml)中获取不需要认证的路径,将其缓存起来
    public void init(FilterConfig config) throws ServletException {
        context = config.getServletContext();
        defaultLoginPage = config.getInitParameter("defaultLoginPage");
        String excludesProp = config.getInitParameter("excludes");
        if (excludesProp != null) {
            StringTokenizer tokenizer = new StringTokenizer(excludesProp, ",");
            while (tokenizer.hasMoreTokens()) {
                String tok = tokenizer.nextToken().trim();
                excludes.add(tok);
            }
        }
    }

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException
    {
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse)res;
        // Reset the defaultLoginPage variable
        String loginPage = defaultLoginPage;
        if (loginPage == null) {
            loginPage = request.getContextPath() + "/login.jsp";
        }
        // Get the page we're on:
        String url = request.getRequestURI().substring(1);
        if (url.startsWith("plugins/")) {
            url = url.substring("plugins/".length());
        }
        // See if it's contained in the exclude list. If so, skip filter execution
        boolean doExclude = false;
        for (String exclude : excludes) {
            if (testURLPassesExclude(url, exclude)) {
                doExclude = true;
                break;   
            }
        }
		
//如果发送请求的URL在excludes范围内中,则终端过滤器链,终止运行,如果不在,则继续运行,执行下一个过滤器
        if (!doExclude) {
            WebManager manager = new WebManager();
            manager.init(request, response, request.getSession(), context);
            if (manager.getUser() == null) {
                response.sendRedirect(getRedirectURL(request, loginPage, null));
                return;
            }
        }
        chain.doFilter(req, res);
    }

    public void destroy() {
    }

    private String getRedirectURL(HttpServletRequest request, String loginPage,
            String optionalParams)
    {
        StringBuilder buf = new StringBuilder();
        try {
            buf.append(request.getRequestURI());
            String qs = request.getQueryString();
            if (qs != null) {
                buf.append("?").append(qs);
            }
        }
        catch (Exception e) {
            Log.error(e.getMessage(), e);
        }
        try {
            return loginPage + "?url=" + URLEncoder.encode(buf.toString(), "ISO-8859-1")
                    + (optionalParams != null ? "&"+optionalParams : "");
        }
        catch (Exception e) {
            Log.error(e.getMessage(), e);
            return null;
        }
    }
}

OpenFire/src/web/WEB-INF/web.xml内容

<filter>
	<filter-name>AuthCheck</filter-name>
	<filter-class>org.jivesoftware.admin.AuthCheckFilter</filter-class>
	<init-param>
		<param-name>excludes</param-name>
		<param-value>
			login.jsp,index.jsp?logout=true,setup/index.jsp,setup/setup-*,.gif,.png,error-serverdown.jsp,setup/clearspace-integration-prelogin.jsp
		</param-value>
	</init-param>
</filter>

猜你喜欢

转载自hbiao68.iteye.com/blog/2020267