關於項目過濾器的使用

這幾天閒着沒事,開始研究起項目過濾器的使用,感覺沒啥意思。蠻記錄下,也當作是學習筆記了!!!
一、 中文編碼過濾器

 <filter>
  		<description>編碼過濾器</description>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceRequestEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
		<init-param>
			<param-name>forceResponseEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	
	  <!-- 中文編碼過濾映射 -->
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

二、 靜態資源過濾器

	<filter>
		<description>處理靜態資源的過濾器</description>
		<filter-name>resourceFilter</filter-name>
		<filter-class>ffcs.cn.common.resourceFilter.ResourceHttpRequestFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>resourceFilter</filter-name>
		<url-pattern>/resource/*</url-pattern>
	</filter-mapping>
    <filter-mapping>
		<filter-name>resourceFilter</filter-name>
		<url-pattern>/upload/*</url-pattern>
	</filter-mapping>

ResourceHttpRequestFilter類

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;

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 org.apache.log4j.Logger;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.support.ServletContextResource;

/**
 * 處理靜態資源的過濾器
 * 用於解決Spring MVC在處理靜態資源(js,css等)的時候也會被攔截器過濾的問題
 * 
 * @author mengyang
 *
 */
public class ResourceHttpRequestFilter implements Filter {
	
	private final Logger logger = Logger.getLogger(getClass());

	public static final String METHOD_HEAD = "HEAD";
	
	public void destroy() {

	}

	public void doFilter(ServletRequest arg0, ServletResponse arg1,
			FilterChain arg2) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest)arg0;
		HttpServletResponse response = (HttpServletResponse)arg1;
		
		Resource resource = getResource(request);
		if (resource == null) {
			logger.debug("No matching resource found - returning 404");
			response.sendError(HttpServletResponse.SC_NOT_FOUND);
			return;
		}

		// check the resource's media type
		MediaType mediaType = getMediaType(request, resource);
		if (mediaType != null) {
			if (logger.isDebugEnabled()) {
				logger.debug("Determined media type [" + mediaType + "] for " + resource);
			}
		}
		else {
			if (logger.isDebugEnabled()) {
				logger.debug("No media type found for " + resource + " - returning 404");
			}
			response.sendError(HttpServletResponse.SC_NOT_FOUND);
			return;
		}

		// header phase
		if (new ServletWebRequest(request, response).checkNotModified(resource.lastModified())) {
			logger.debug("Resource not modified - returning 304");
			return;
		}
		setHeaders(response, resource, mediaType);

		// content phase
		if (METHOD_HEAD.equals(request.getMethod())) {
			logger.trace("HEAD request - skipping content");
			return;
		}
		writeContent(response, resource);

	}

	public void init(FilterConfig arg0) throws ServletException {

	}
	
	//獲取請求的靜態資源
	protected Resource getResource(HttpServletRequest request) throws UnsupportedEncodingException {
		
		String URI = URLDecoder.decode(request.getRequestURI(), "utf-8");
		String context = request.getContextPath();
		String path = URI.substring(URI.indexOf(context) + context.length());
		Resource resource = new ServletContextResource(request.getSession().getServletContext(), path);
		if (resource.exists() && resource.isReadable()) {
			if (logger.isDebugEnabled()) {
				logger.debug("Found matching resource: " + resource);
			}
			return resource;
		}
		else if (logger.isTraceEnabled()) {
			logger.trace("Relative resource doesn't exist or isn't readable: " + resource);
		}
		return null;
	}

	//獲取資源的MediaType
	protected MediaType getMediaType(HttpServletRequest request, Resource resource) {
		String mimeType = request.getSession().getServletContext().getMimeType(resource.getFilename());
		return (StringUtils.hasText(mimeType) ? MediaType.parseMediaType(mimeType) : null);
	}

	//設置響應頭部
	protected void setHeaders(HttpServletResponse response, Resource resource, MediaType mediaType) throws IOException {
		long length = resource.contentLength();
		if (length > Integer.MAX_VALUE) {
			throw new IOException("Resource content too long (beyond Integer.MAX_VALUE): " + resource);
		}
		response.setContentLength((int) length);
		response.setContentType(mediaType.toString());
	}

	//直接把資源流寫到響應中
	protected void writeContent(HttpServletResponse response, Resource resource) throws IOException {
		
		FileCopyUtils.copy(resource.getInputStream(), response.getOutputStream());
	}

}

也可以在application配置靜態資源過濾器

<!-- 靜態資源 -->
	<mvc:annotation-driven></mvc:annotation-driven>
	<mvc:resources location="/resource/" mapping="/resource/**"
		cache-period="864000" />

三、 登錄驗證過濾器
該過濾器主要原理就是根據是否存在session信息判斷是否處於登錄狀態,不是就返回登錄頁


	<!-- ************************登錄驗證過濾 **************************-->
		<filter>
        <description>登錄驗證</description>
        <filter-name>loginFilter</filter-name>
        <filter-class>ffcs.cn.common.loginFilter.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>loginFilter</filter-name>
        <url-pattern>/peam/*</url-pattern>
    </filter-mapping>
	

LoginFilter類

import java.io.IOException;
import java.io.PrintWriter;

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 ffcs.cn.common.Constants;

/**
 * 驗證用戶登錄
 * @author zhangy
 *
 */
public class LoginFilter implements Filter{

    public void init(FilterConfig filterConfig) throws ServletException {
        
        
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;  
        HttpServletResponse response = (HttpServletResponse) servletResponse; 
        //查詢session是否有用戶信息
        Object user =  request.getSession().getAttribute(Constants.LOGIN_USER_SESSION);
        if(user!=null){
             chain.doFilter(request, response);
        }else {
        	 
             request.setCharacterEncoding("UTF-8");
             response.setCharacterEncoding("UTF-8");
             response.setContentType("text/html; charset=UTF-8");
             PrintWriter out = response.getWriter();
             String loginPage = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+"/MySsh";
             StringBuilder builder = new StringBuilder();
             builder.append("<script type=\"text/javascript\">");
             builder.append("alert('網頁過期,請重新登錄!');");
             builder.append("window.top.location.href='");
             builder.append(loginPage);
             builder.append("';");
             builder.append("</script>");
             out.print(builder.toString());
        }
            
    }

	@Override
	public void destroy() {	
	}
}

四、 驗證碼過濾器
原理和登錄驗證過濾器一樣,也是檢查session信息

	
	<!-- ************************驗證碼過濾 **************************-->
	<filter>
		<description>驗證碼</description>
		<filter-name>verificationCodeFilter</filter-name>
		<filter-class>ffcs.cn.common.VerificationCodeFilter.VerificationCodeFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>verificationCodeFilter</filter-name>
		<url-pattern>/yzm_check</url-pattern>
	</filter-mapping>

VerificationCodeFilter類

import java.io.IOException;

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;



/**
 * 驗證碼判斷
 * @author 
 *
 */
public class VerificationCodeFilter implements Filter{

	@Override
	public void destroy() {
		
		
	}

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
			FilterChain filterChain) throws IOException, ServletException {
		 HttpServletRequest request = (HttpServletRequest) servletRequest;    
	     HttpServletResponse response = (HttpServletResponse) servletResponse; 
	     String checkcode =request.getParameter("t_checkcode");
	     String rightCode = (String)request.getSession().getAttribute("rand");
	     if(checkcode!=null && ("9999".equals(checkcode)||checkcode.equals(rightCode))){
	    	 //驗證碼正確
	    	 filterChain.doFilter(request, response);
	     }else{
	    	 //驗證碼錯誤
	    	 response.setContentType("application/json;charset=UTF-8");
	    	 response.getWriter().write("{\"message\":\"驗證碼錯誤\",\"data\":null,\"success\":false}");
	     }

	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		
		
	}

	

}

五、防sql注入過濾

	<!-- ************************防sql注入過濾 **************************-->
	<filter>
		<filter-name>XssFilter</filter-name>
		<filter-class>ffcs.cn.common.xssFilter.XssFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>XssFilter</filter-name>
		<url-pattern>/*</url-pattern>
		<dispatcher>REQUEST</dispatcher>
	</filter-mapping>

XssFilter類

import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

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 org.codehaus.jackson.map.ObjectMapper;

public class XssFilter implements Filter {

	FilterConfig filterConfig;
	
	private ArrayList<String> filterURL = new ArrayList<String>();
	private ArrayList<String> excludedFilterURL = new ArrayList<String>();
	
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
        String url = Globals.getGlobalProperty("filter.xss.url");
        System.out.println("------------conf xss  sql  filter------------"+url);
        String[] urlArr = url.split(";");
        for (String str:urlArr)
        {
        	filterURL.add(str.trim());
        }
        
        //設置不過濾的url @Author linph
        String excludedUrl = Globals.getGlobalProperty("filter.excluded.url");
        String[] excludedUrlArr = excludedUrl.split(";");
        for (String str:excludedUrlArr) {
        	excludedFilterURL.add(str.trim());
        }
    }
	public void destroy() {
        this.filterConfig = null;
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain filterChain) throws IOException, ServletException {  
    	HttpServletRequest req = (HttpServletRequest) request;
    	HttpServletResponse resp = (HttpServletResponse) response;
    	request.setCharacterEncoding("utf-8");
    	String url = req.getRequestURI(); 	
    	boolean isSpecialUrl = false;
    	//是否跳過過濾
    	boolean isExcluded = false;
    	if (filterURL.contains(url)) {
    		isSpecialUrl = true;
    	}
    	if (excludedFilterURL.contains(url)) {
    		isExcluded = true;
    	}
    	
    	if (!isExcluded) {
    		Map map = request.getParameterMap();
    		Set keySet = map.keySet();
    		for (Object object : keySet) {
    			String paraName = object.toString();
    			if (isSpecialUrl && "flowXml".equals(paraName)) {
    				continue;
    			}
    			String[] values = request.getParameterValues(paraName);
    			
    			if (values != null && isSpecialUrl && "newTxt".equals(paraName)) {
    				continue;
    			} else {
    				for (int i = 0; i < values.length; i++) {
    					String val = values[i];
    					try{
    						val = java.net.URLDecoder.decode(val, "UTF-8"); 
    					}catch(Exception e){
    						e.printStackTrace();
    					}
    					if(sqlValidator(val) || scriptValidator(val)){
    						//String path = req.getContextPath();
    						//String basePath = req.getScheme()+"://"+req.getServerName()+":"+req.getServerPort()+path; 
    						if (isAjaxRequest(req)) {  
    							ObjectMapper mapper = new ObjectMapper();
    							resp.setContentType("application/json;charset=utf-8");
    							resp.setCharacterEncoding("UTF-8");
    							resp.setHeader("Cache-Control", "no-cache");
    							resp.getWriter().write(mapper.writeValueAsString("錯誤"));
    							resp.getWriter().flush();
    							resp.getWriter().close();
    							return;
    						} else {
    							//req.getRequestDispatcher("/WEB-INF/views/common/err.jsp").forward(request, response);
    							values[i] = cleanXSS(val);
    						}
    					}
    				}
    			}
    		}
		}
		filterChain.doFilter(request, response);
	}
	
	public static boolean isAjaxRequest(HttpServletRequest request) {  
		String requestType = request.getHeader("X-Requested-With");  
		return requestType != null && requestType.equals("XMLHttpRequest");
    } 

	private boolean sqlValidator(String fieldValue){
		//禁止OR、聯合執行語句方式注入
		String parStr = "\\w*((%27)|(\\')\\s*)(((%6F)|o|(%4F))((%72)|r|(%52))|(union))";
		Pattern pattern = Pattern.compile(parStr, Pattern.CASE_INSENSITIVE);
		Matcher matcher = pattern.matcher(fieldValue);
		if(matcher.find())
			return true;
		//禁止以大於、小於、等於、註釋的方式繞過原語句,注入SQL
		parStr = "((%3C)|(<)|(0x3C)|(%3D)|(=)|(0x3D)|(%3E)|(>)|(0x3E))[^\\n]*((%27)|(\\')|(0x27)|(%3B)|(:)|(0x3B))";
		pattern = Pattern.compile(parStr, Pattern.COMMENTS|Pattern.CASE_INSENSITIVE);
		matcher = pattern.matcher(fieldValue);
		if(matcher.find())
			return true;
		//禁止有危害SQL關鍵字和利用引號分號非法結束原語句,注入SQL//(and)|(exec)|(insert)|(select)|(delete)|(update)|(count)|(*)|(%)|(chr)|(mid)|(master)|(truncate)|(char)|(declare)
		//parStr = "(union)|(select)|(concat)|(drop)|(truncate)|(delete)|(((\\';)+|(\\-\\-)+).*)|(0x7c)|(\\|)|(%7C)|(0x60)|(`)|(%60)";
		parStr = "(?:')|(?:([a-z0-9A-Z_\\s\\(\\)]+\\-\\-))|(/\\*(?:.|[\\n\\r])*?\\*/)|(\\';)|(0x7c)|(\\|)|(`)|"  
            + "(\\b(select|and|or|update|delete|insert|trancate|char|into|substr|mid|\\*|ascii|declare|exec|count|master|into|drop|execute)[\\s+\\(\\)]\\b)";
		pattern = Pattern.compile(parStr, Pattern.COMMENTS|Pattern.CASE_INSENSITIVE);
		matcher = pattern.matcher(fieldValue);
		if(matcher.find())
			return true;
		return false;
	}
	
	private boolean scriptValidator(String fieldValue){
		//禁止HTML及SCRIPT標籤
		String parStr = "((%3C)|<)\\s*((%2F)|\\/)*\\s*[A-Za-z0-9%]+\\s*((%3E)|>)";
		Pattern pattern = Pattern.compile(parStr, Pattern.COMMENTS|Pattern.CASE_INSENSITIVE);
		Matcher matcher = pattern.matcher(fieldValue);
		if(matcher.find()||fieldValue.toLowerCase().indexOf("script")>=0)
			return true;
		//判斷IMG及SRC注入方式
		parStr = "(((%3C)|<)\\s*((%69)|i|(%49))((%6D)|m|(%4D))((%67)|g|(%47))[^\\n]+((%3E)|>))|(((%53)|s|(%73))((%72)|r|(%52))((%43)|c|(%63)))";
		pattern = Pattern.compile(parStr, Pattern.COMMENTS|Pattern.CASE_INSENSITIVE);
		matcher = pattern.matcher(fieldValue);
		if(matcher.find())
			return true;
		//判斷常用HTML事件函數及轉義字符攻擊方式
		parStr =  "\\b(fromCharCode|onmouse|onclick|ondblclick|onload|onblur|onFocus|onkeydown|onkeypress|onkeyup|&quot|&apos|&amp|&lt|&gt|(&\\#[0-9a-fA-F]+)|'|\"|`)";
		pattern = Pattern.compile(parStr, Pattern.COMMENTS|Pattern.CASE_INSENSITIVE);
		matcher = pattern.matcher(fieldValue);
		if(matcher.find())
			return true;
		//禁止訪問WEB-INF、XML、UNICODE
		parStr = "(WEB\\-INF)|(xml)|((\\\\)(u)[0-9a-fA-F]{2,5})";
		pattern = Pattern.compile(parStr, Pattern.COMMENTS|Pattern.CASE_INSENSITIVE);
		matcher = pattern.matcher(fieldValue);
		if(matcher.find())
			return true;
		return false;
	}

	private String cleanXSS(String value) {
		value = value.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
		value = value.replaceAll("\\(", "&#40;").replaceAll("\\)", "&#41;");
		value = value.replaceAll("'", "&#39;");
		value = value.replaceAll("eval\\((.*)\\)", "");
		value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']","\"\"");
		value  = value.replaceAll("(?i)script", ""); 
		//value = value.replaceAll("script", "");
		return value;
	}
}
import java.io.InputStream;
import java.util.Properties;

public class Globals {
	private static Properties initProps = null;

	public static String getGlobalProperty(String name) {
		loadProperties();
		if(initProps.getProperty(name) != null && !initProps.getProperty(name).equals(""))
			return initProps.getProperty(name);
		else
			return "";
	}
	
	public static boolean getBooleanGlobalProperty(String name) {
		loadProperties();
		if(initProps.getProperty(name) != null && !initProps.getProperty(name).equals("")) {
			if(initProps.getProperty(name).equals("true"))
				return true;
			else return false;
		}
		else return false;
	}
	
	public static int getIntGlobalProperty(String name) {
		String prop = getGlobalProperty(name);
		return Integer.parseInt(prop);
	}
	
	private synchronized static void loadProperties() {
		if (initProps == null) {
			initProps = new Properties();
			InputStream in = null;
			try {
				in = Globals.class.getResourceAsStream("/global.properties");
				initProps.load(in);
			} catch (Exception e) {
				System.err.println("Load global.properties configure file error!");
			} finally {
				try {
					if (in != null) {
						in.close();
					}
				} catch (Exception e) {
				}
			}
		}
	}
	
	
}```

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章