📄 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.*;
/**
* <p>Title: 权限过滤器</p>
*
* <p>Description: 权限过滤器主类,需要配置到Web.xml文件中才会起作用,配置示例如下:</p>
* <filter>
* <filter-name>SecurityFilter</filter-name>
* <filter-class>dev.trade.common.securityfilter.filter.SecurityFilter</filter-class>
* <init-param>
* <param-name>config</param-name>
* <param-value>/WEB-INF/securityfilter-config.xml</param-value>
* <description>Configuration file location (default)</description>
* </init-param>
* </filter>
* <filter-mapping>
* <filter-name>SecurityFilter</filter-name>
* <url-pattern>/*</url-pattern>
* </filter-mapping>
*
* <p>Copyright: Copyright (c) 2006</p>
*
* <p>Company: </p>
*
* @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;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -