www.pudn.com > SecurityFilter.rar > SecurityFilter.java


package dev.trade.common.securityfilter.filter; 
 
import java.io.*; 
import java.net.*; 
import java.security.*; 
import java.util.*; 
import javax.servlet.*; 
import javax.servlet.http.*; 
import org.apache.log4j.*; 
import dev.trade.common.securityfilter.util.*; 
import dev.trade.common.securityfilter.authenticator.*; 
import dev.trade.common.securityfilter.authenticator.Authenticator; 
import dev.trade.common.securityfilter.config.*; 
 
/** 
 * 

Title: 权限过滤器

* *

Description: 权限过滤器主类,需要配置到Web.xml文件中才会起作用,配置示例如下:

* * SecurityFilter * dev.trade.common.securityfilter.filter.SecurityFilter * * config * /WEB-INF/securityfilter-config.xml * Configuration file location (default) * * * * SecurityFilter * /* * * *

Copyright: Copyright (c) 2006

* *

Company:

* * @author Zheng YanNan * @version 1.0 */ public class SecurityFilter implements Filter{ private static Logger log = Logger.getLogger(SecurityFilter.class); public static final String CONFIG_FILE_KEY = "config"; public static final String DEFAULT_CONFIG_FILE = "/WEB-INF/securityfilter-config.xml"; public static final String VALIDATE_KEY = "validate"; public static final String TRUE = "true"; protected FilterConfig config; protected List patternList; protected URLPatternFactory patternFactory; protected Authenticator authenticator; protected SecurityConfig securityConfig; /** * 初始化权限过滤器 * @param config filter configuration object */ public void init(FilterConfig config) throws ServletException{ this.config = config; String configFile = null; try{ // 解析配置文件 configFile = config.getInitParameter(CONFIG_FILE_KEY); if(configFile == null){ configFile = DEFAULT_CONFIG_FILE; } URL configURL = config.getServletContext().getResource(configFile); // // validate config file? // boolean validate = TRUE.equalsIgnoreCase(config.getInitParameter(VALIDATE_KEY)); securityConfig = new SecurityConfig(false); securityConfig.loadConfig(configURL); // 创建验证器 authenticator = AuthenticatorFactory.createAuthenticator(config, securityConfig); // 创建范式列表 patternFactory = new URLPatternFactory(); patternList = new ArrayList(); int order = 1; List constraints = securityConfig.getSecurityConstraints(); for(Iterator cIter = constraints.iterator(); cIter.hasNext(); ){ SecurityConstraint constraint = (SecurityConstraint)cIter.next(); for(Iterator rIter = constraint.getWebResourceCollections().iterator(); rIter.hasNext(); ){ WebResourceCollection resourceCollection = (WebResourceCollection)rIter.next(); for(Iterator pIter = resourceCollection.getURLPatterns().iterator(); pIter.hasNext(); ){ URLPattern pattern = patternFactory.createURLPattern((String)pIter.next(), constraint, resourceCollection, order++); patternList.add(pattern); } } } Collections.sort(patternList); } catch(java.io.IOException ioe){ log.error("无法打开配置文件:" + configFile, ioe); throw new ServletException("无法打开配置文件:" + configFile,ioe); } catch(org.xml.sax.SAXException se){ log.error("无法解析配置文件:" + configFile, se); throw new ServletException("无法解析配置文件:" + configFile,se); } catch(Exception e){ log.error("发生错误!" + e); throw new ServletException("发生错误:",e); } } /** * 权限过滤 * @param request ServletRequest * @param response ServletResponse * @param chain FilterChain * @throws IOException * @throws ServletException */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException{ HttpServletRequest hReq = (HttpServletRequest)request; HttpServletResponse hRes = (HttpServletResponse)response; SecurityRequest wrappedRequest; // 检查请求是否已被验证过(减少验证次数) if(!TRUE.equals(request.getAttribute(RequestUtils.ALREADY_PROCESSED))){ // 设置已验证标记 request.setAttribute(RequestUtils.ALREADY_PROCESSED, TRUE); // 创建一个URL匹配器 URLPatternMatcher patternMatcher = patternFactory.createURLPatternMatcher(); // 获取已保存的请求,否则返回空(主要用于登录后跳转回原请求URL) SavedRequest savedRequest = RequestUtils.getSavedRequest(hReq); // 包装当前请求 wrappedRequest = new SecurityRequest(hReq, savedRequest, authenticator); URLPattern match = null; try{ // 检查是否为登出请求,并进行相应处理 if(authenticator.checkAndDoLogout(wrappedRequest, hRes, patternMatcher)){ // If logging out destroy and recreate session hReq.getSession().invalidate(); hReq.getSession(true); } // 检查是否为登录提交请求,并进行相应处理 if(authenticator.checkAndDoLogin(wrappedRequest, hRes, patternMatcher)){ return; } // 检查是否需要跳过权限验证 if(!authenticator.bypassSecurityForThisRequest(wrappedRequest, patternMatcher)){ // check if request matches security constraint match = matchPattern(wrappedRequest.getMatchableURL(), wrappedRequest.getMethod(), patternMatcher); } } catch(Exception e){ throw new ServletException("URL匹配错误:" + wrappedRequest.getMatchableURL(), e); } // 检查当前请求的权限约束 if(match != null){ AuthConstraint authConstraint = match.getSecurityConstraint().getAuthConstraint(); if(authConstraint != null){ Collection roles = authConstraint.getRoles(); Principal principal = wrappedRequest.getUserPrincipal(); // 如果允许的角色列表为空, 所有的请求都通过, 可以跳过登录 if(!roles.isEmpty() && principal == null){ // user needs to be authenticated try{ authenticator.showLogin(hReq, hRes); } catch(Exception ex){ throw new ServletException("登录页面转向失败:" + wrappedRequest.getMatchableURL(), ex); } return; } else{ boolean authorized = roles.isEmpty(); for(Iterator i = roles.iterator(); i.hasNext() && !authorized; ){ String role = (String)i.next(); // TODO: if *, do you need to have at least one role to be authorized? // if so, we need to iterate through the roles defined in config file or change the // realm inteface to get a list of roles for the user (both solutions are undesireable) if("*".equals(role) || authenticator.isUserInRole(principal, role)){ authorized = true; } } if(!authorized){ // 访问被禁止(没有权限) try{ authenticator.showForbidden(hReq, hRes); } catch(Exception ex){ throw new ServletException("访问禁止页面转向失败:" + wrappedRequest.getMatchableURL(), ex); } return; } } } } // send wrapped request down the chain request = wrappedRequest; } chain.doFilter(request, response); } /** * Destroy the filter, releasing resources. */ public void destroy(){ } /** * 查找符合请求URL 与 请求方法的URL范式 * @param pattern String * @param httpMethod String * @param matcher URLPatternMatcher * @return URLPattern * @throws Exception */ protected URLPattern matchPattern(String pattern, String httpMethod, URLPatternMatcher matcher) throws Exception{ // PERFORMANCE IMPROVEMENT OPPORTUNITY: cahce pattern matches Iterator i = patternList.iterator(); URLPattern urlPattern = null; while(i.hasNext()){ urlPattern = (URLPattern)i.next(); if(matcher.match(pattern, httpMethod, urlPattern)){ return urlPattern; } } return null; } /** * Set the filter configuration, included for WebLogic 6 compatibility. * * @param config filter configuration object */ public void setFilterConfig(FilterConfig config) throws ServletException{ init(config); } /** * Get the filter config object, included for WebLogic 6 compatibility. */ public FilterConfig getFilterConfig(){ return config; } }