/* ==================================================================
* Created [2009-4-27 下午11:32:55] by Jon.King
* ==================================================================
* TSS
* ==================================================================
* mailTo:jinpujun@hotmail.com
* Copyright (c) Jon.King, 2009-2012
* ==================================================================
*/
package com.jinhe.tss.component.param.extend;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.Element;
import com.jinhe.tss.component.param.ParamManager;
import com.jinhe.tss.core.exception.BusinessException;
import com.jinhe.tss.core.exception.BusinessServletException;
import com.jinhe.tss.core.sso.SSOConstants;
import com.jinhe.tss.core.sso.context.Context;
import com.jinhe.tss.core.util.EasyUtils;
import com.jinhe.tss.core.util.XMLDocUtil;
/**
* <p> PermissionCheckFilter.java </p>
*
* 应用地址访问权限控制检测过滤器
*
* @author Jon.King 2008/12/19 10:59:06
*/
public class AccessingCheckFilter implements Filter {
private Log log = LogFactory.getLog(AccessingCheckFilter.class);
public void init(FilterConfig filterConfig) throws ServletException {
log.info("应用地址访问权限控制过滤器初始化完成!appCode=" + Context.getApplicationContext().getCurrentAppCode());
}
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
if(!checkIp(request.getRemoteAddr())) {
log.info("黑名单(" + request.getRemoteAddr() + ")用户试图访问系统被拒绝。");
throw new BusinessServletException("您的ip" + request.getRemoteAddr() + " 地址在黑名单里,如有疑问请联系管理员!");
}
HttpSession session = req.getSession(false);
if(session == null){
chain.doFilter(request, response);
return;
}
//检测权限
List<Object> userRights = new ArrayList<Object>();
try {
List<?> userRightsInSession = (List<?>) session.getAttribute(SSOConstants.USER_RIGHTS_IN_SESSION);
if(userRightsInSession != null) {
userRights.addAll(userRightsInSession);
}
String operatorName = (String) session.getAttribute(SSOConstants.LOGINNAME_IN_SESSION);
if(operatorName != null) {
userRights.add(operatorName);
}
}catch(Exception e){
}
String servletPath = req.getRequestURI().substring(req.getContextPath().length());
AccessingChecker checker = AccessingChecker.getInstance();
log.info("权限检测:" + servletPath);
if (!checker.checkPermission(userRights, servletPath)) {
log.info("权限检测失败");
if(checker.get404URL() != null){
((HttpServletResponse)response).sendRedirect(checker.get404URL());
return;
}
throw new BusinessServletException("访问控制检测失败,您无权访问本页面");
}
log.info("权限检测通过");
chain.doFilter(request, response);
}
public final static String LIMITED_IP_LIST = "limited_ip_list";
/**
* 检查ip地址是否在受限的黑名单里。
* @param remoteAddr
* @return
* 不受限:true 受限:false
*/
private boolean checkIp(String remoteAddr) {
String limitedIPs;
try{
limitedIPs = ParamManager.getValue(LIMITED_IP_LIST); // 格式为ip1,ip2,ip3....
} catch (Exception e){
limitedIPs = null;
}
return limitedIPs == null || limitedIPs.indexOf(remoteAddr) == -1;
}
}
/**
* <p> PermissionChecker.java </p>
*
* 权限检测器。
*
* 权限配置文件格式:
* <rightConfig>
* <servlet name="test.do" right="权限ID1,权限ID2,Admin"/>
* <servlet name="param!*.action" right="权限ID1,权限ID3,Admin,JonKing"/>
* </rightConfig>
*
* @author Jon.King 2008/12/19 10:59:06
*/
class AccessingChecker {
/** 权限配置文件 */
private static final String RIGHT_CONFIG_FILE_NAME = "META-INF/right-config.xml";
private static Map<String, Set<String>> rightsMap;
private static String THE_404_URL;
private AccessingChecker() {
try {
rightsMap = parser(RIGHT_CONFIG_FILE_NAME);
} catch (Exception e) {
throw new BusinessException("权限配置初始化失败!", e);
}
}
private static AccessingChecker instance;
public static AccessingChecker getInstance(){
if(instance == null){
instance = new AccessingChecker();
}
return instance;
}
/**
* 检查用户是否拥有相应的权限。
* 分两步:
* 1、检查用户拥有的角色是否足够(即是否在应用程序的权限角色之中)
* 2、检查用户的账号是否在应用程序允许访问的用户名单中
* 两者有一个通过即可。
* 注:账号和角色都放userRights里了,
*
* @param userRigths
* 用户拥有的权限
* @param servletPath
* 检测的请求路径
* @return
* @throws Exception
*/
public boolean checkPermission(List<Object> userRights, String servletPath) {
if (rightsMap == null || rightsMap.isEmpty()) {
return true;
}
Set<String> rights = rightsMap.get(servletPath);
// 如果访问权限控制配置为空,则不需要控制,直接放行。
if (rights == null || rights.isEmpty()) {
return true;
}
// 访问权限控制配置不为空,则用户必须拥有足够的权限才能访问
if( !EasyUtils.isNullOrEmpty(userRights)) {
for (Object temp : userRights) {
// 用户角色ID有可能为Long类型,需要toString一下,因为rights里根据配置文件解析出来的都是String形式。
if (temp != null && rights.contains(temp.toString()))
return true;
}
}
return false;
}
public String get404URL(){
return THE_404_URL;
}
/**
* 解析应用程序权限访问控制配置文件。
* 把应用程序有权限访问的角色ID 以及 账号统一放在Set里。
*
* @param configFile
* @return
* @throws Exception
*/
private Map<String, Set<String>> parser(String configFile) throws Exception {
Map<String, Set<String>> rightsMap = new HashMap<String, Set<String>>();
if (configFile == null || "".equals(configFile)) {
return rightsMap;
}
Document doc = XMLDocUtil.createDoc(configFile);
Element root = doc.getRootElement();
THE_404_URL = root.attributeValue("url_404");
for (Iterator<?> it = root.elementIterator("servlet"); it.hasNext();) {
Element servletNode = (Element) it.next();
String name = servletNode.attributeValue("name");
if (name == null || "".equals(name)) {
continue;
}
String role = servletNode.attributeValue("right");
if ( !EasyUtils.isNullOrEmpty(role) ) {
Set<String> rightSet = new HashSet<String>();
String[] rights = role.split(",");
for (int i = 0; i < rights.length; i++) {
rightSet.add(rights[i]);
}
rightsMap.put(name, rightSet);
}
}
return rightsMap;
}
}