Java使用過濾器防止SQL注入XSS腳本注入的實現(xiàn)
前幾天有個客戶在系統(tǒng)上寫了一段html語句,打開頁面就顯示一張炒雞大的圖片,影響美觀。后來仔細想想,幸虧注入的僅僅是html語句,知道嚴(yán)重性后,馬上開始一番系統(tǒng)安全配置。
一. 定義過濾器
package com.cn.unit.filter;
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 org.apache.commons.lang.StringUtils;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
/**
* 過濾器
* Created by adonis on 2020/12/12
*/
public class SafeFilter implements Filter{
// 配置信息對象
public FilterConfig filterConfig;
/**
* 初始化
* 與我們編寫的Servlet程序一樣,F(xiàn)ilter的創(chuàng)建和銷毀由WEB服務(wù)器負責(zé)。
* Web應(yīng)用程序啟動時,Web服務(wù)器將創(chuàng)建Filter的實例對象,并調(diào)用其init方法,讀取web.xml配置,
* 完成對象的初始化功能,從而為后續(xù)的用戶請求作好攔截的準(zhǔn)備工作。
* Filter對象只會創(chuàng)建一次,init方法也只會執(zhí)行一次。
* 開發(fā)人員通過init方法的參數(shù),可獲得代表當(dāng)前Filter配置信息的FilterConfig對象。
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
filterConfig = config;
}
/**
* 攔截請求
* 這個方法完成實際的過濾操作。當(dāng)客戶請求訪問與過濾器關(guān)聯(lián)的URL的時候,Servlet過濾器將先執(zhí)行doFilter方法。
* FilterChain參數(shù)用于訪問后續(xù)過濾器。
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String enctype = httpRequest.getContentType();
if(StringUtils.isNotBlank(enctype) && enctype.contains("multipart/form-data")){
// 上傳文件
CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(
httpRequest.getSession().getServletContext());
MultipartHttpServletRequest multipartRequest = commonsMultipartResolver.resolveMultipart(httpRequest);
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(multipartRequest);
chain.doFilter(xssRequest, response);
}else{
// 普通表單和Ajax
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
chain.doFilter(xssRequest, response);
}
}
/**
* 銷毀
* Filter對象創(chuàng)建后會駐留在內(nèi)存,當(dāng)Web應(yīng)用移除或服務(wù)器停止時才銷毀。在Web容器卸載Filter對象之前被調(diào)用。
* 該方法在Filter的生命周期中僅執(zhí)行一次。在這個方法中,可以釋放過濾器使用的資源。
*/
@Override
public void destroy() {
this.filterConfig = null;
}
}
二. 過濾包裝器,實現(xiàn)參數(shù)值過濾
package com.cn.unit.filter;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* 用戶請求包裝類
* Created by adonis on 2020/12/12
*/
public class SafeHttpServletRequestWrapper extends HttpServletRequestWrapper{
public SafeHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getParameter(String name) {
String value = super.getParameter(name);
if (value != null) {
value = xssEncode(value);
}
return value;
}
@Override
public String[] getParameterValues(String name) {
String[] value = super.getParameterValues(name);
if(value != null){
for (int i = 0; i < value.length; i++) {
value[i] = xssEncode(value[i]);
}
}
return value;
}
@Override
public Map getParameterMap() {
return super.getParameterMap();
}
/**
* 請求頭不過濾
*/
@Override
public String getHeader(String name) {
return super.getHeader(name);
}
/**
* 將容易引起注入的關(guān)鍵字的半角字符直接替換成全角字符
* @param value 過濾前的值
* @return 過濾后的值
*/
private static String xssEncode(String value) {
if (value == null || value.isEmpty()) {
return value;
}
// 防SQL注入轉(zhuǎn)義
value = StringEscapeUtils.escapeSql(value);
// HTML防注入,個人建議使用第三種
// 1.防HTML注入轉(zhuǎn)義(HtmlUtils工具類,漢字不轉(zhuǎn)義,雙引號轉(zhuǎn)義,存在JSON封裝需要反轉(zhuǎn)義)
value = HtmlUtils.htmlEscape(value);
/*
// 2.防HTML注入轉(zhuǎn)義(StringEscapeUtils工具類,漢字也轉(zhuǎn)義,取出時需要反轉(zhuǎn)義)
// value = StringEscapeUtils.escapeHtml(value);
// 3.字符串替換法(通過各種循環(huán)替換字符串測試,最終還是replace替換效果最佳)
value = value.replaceAll("<", "<");
value = value.replaceAll(">", ">");
value = value.replaceAll("'", "'");
value = value.replaceAll(";", "﹔");
value = value.replaceAll("&", "&");
value = value.replaceAll("%", "﹪");
value = value.replaceAll("#", "#");
value = value.replaceAll("select", "seleᴄt");// "c"→"ᴄ"
value = value.replaceAll("truncate", "trunᴄate");// "c"→"ᴄ"
value = value.replaceAll("exec", "exeᴄ");// "c"→"ᴄ"
value = value.replaceAll("join", "jᴏin");// "o"→"ᴏ"
value = value.replaceAll("union", "uniᴏn");// "o"→"ᴏ"
value = value.replaceAll("drop", "drᴏp");// "o"→"ᴏ"
value = value.replaceAll("count", "cᴏunt");// "o"→"ᴏ"
value = value.replaceAll("insert", "ins℮rt");// "e"→"℮"
value = value.replaceAll("update", "updat℮");// "e"→"℮"
value = value.replaceAll("delete", "delet℮");// "e"→"℮"
value = value.replaceAll("script", "sᴄript");// "c"→"ᴄ"
value = value.replaceAll("cookie", "cᴏᴏkie");// "o"→"ᴏ"
value = value.replaceAll("iframe", "ifram℮");// "e"→"℮"
value = value.replaceAll("onmouseover", "onmouseov℮r");// "e"→"℮"
value = value.replaceAll("onmousemove", "onmousemov℮");// "e"→"℮"*/
return value;
}
}
三. 配置web.xml添加過濾器
<!-- 配置過濾器防止SQL注入XSS注入 --> <filter> <filter-name>XssSqlFilter</filter-name> <filter-class>com.cn.unit.filter.SafeFilter</filter-class> </filter> <filter-mapping> <filter-name>XssSqlFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
配置各節(jié)點簡單介紹:
| 節(jié)點名 | 介紹 |
|---|---|
| <filter> | 指定一個過濾器 |
| <filter-name> | 用于為過濾器指定一個名字,該元素的內(nèi)容不能為空 |
| <filter-class> | 指定過濾器的完整的限定類名 |
| <init-param> | 為過濾器指定初始化參數(shù)。在過濾器中,可以使用FilterConfig接口對象來訪問初始化參數(shù) |
| <param-name> | <init-param>的子元素,指定參數(shù)的名字 |
| <param-value> | <init-param>的子元素,指定參數(shù)的值 |
| <filter-mapping> | 設(shè)置一個Filter所負責(zé)攔截的資源??赏ㄟ^Servlet名稱或資源訪問的請求路徑指定 |
| <filter-name> | 子元素用于設(shè)置filter的注冊名稱。該值必須是在<filter>元素中聲明過的過濾器的名字 |
| <url-pattern> | 設(shè)置 filter 所攔截的請求路徑(過濾器關(guān)聯(lián)的URL樣式) |
| <servlet-name> | 指定過濾器所攔截的Servlet名稱 |
| <dispatcher> | 指定過濾器所攔截的資源被 Servlet 容器調(diào)用的方式,默認(rèn)REQUEST |
四. 靜態(tài)資源跳過過濾
在實際開發(fā)的過程中,js、css等靜態(tài)資源也進行過濾,消耗服務(wù)器性能,因此把一些不必要過濾的直接跳過過濾器,實現(xiàn)如下:
4.1 在web.xml配置文件中添加參數(shù),保存靜態(tài)資源所在的路徑
<init-param> <param-name>excludeFilter</param-name><!-- 靜態(tài)資源不進行過濾,如js、css文件 --> <param-value>/document/;/ligentres/</param-value> </init-param>
如圖:

4.2 過濾器初始化方法,讀取靜態(tài)資源所在的路徑
public FilterConfig filterConfig;
public String[] excludeFilterArray;
@Override
public void init(FilterConfig config) throws ServletException {
filterConfig = config;
// 讀取web配置文件中的靜態(tài)資源所在路徑
String excludeFilter = filterConfig.getInitParameter("excludeFilter");
excludeFilterArray = excludeFilter.split(";");
}
4.3 過濾器攔截請求,若是靜態(tài)資源所在的路徑直接跳過過濾器
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String uri = httpRequest.getRequestURI();
// 靜態(tài)資源直接跳過,不進行過濾
if(uri==null||this.isContains(uri, excludeFilterArray)) {
chain.doFilter(request, response);
return;
}
......
}
// 判斷數(shù)組是否包含某一元素
public boolean isContains(String uri, String[] regx) {
boolean result = false;
for (int i = 0; i < regx.length; i++) {
if (uri.indexOf(regx[i]) != -1) {
return true;
}
}
return result;
}
五. 大功告成
借鑒前人的經(jīng)驗,一開始測試的時候發(fā)現(xiàn),普通的表單提交和ajax提交可以過濾其參數(shù),但上傳文件時就無法進入過濾了。
后來經(jīng)過研究,用于處理文件上傳的 MultipartResolver ,當(dāng)收到請求時,DispatcherServlet 的 checkMultipart() 方法會調(diào)用 MultipartResolver 的 isMultipart() 方法判斷請求中是否包含文件。如果請求數(shù)據(jù)中包含文件,則調(diào)用 MultipartResolver 的 resolveMultipart() 方法對請求的數(shù)據(jù)進行解析,然后將文件數(shù)據(jù)解析成 MultipartFile 并封裝在 MultipartHttpServletRequest 對象中,最后傳遞給 Controller。因此我們只需要在定義過濾器時,先獲取請求頭判斷是否為文件上傳,若是再對數(shù)據(jù)進行解析便可。
到此這篇關(guān)于Java使用過濾器防止SQL注入XSS腳本注入的實現(xiàn)的文章就介紹到這了,更多相關(guān)Java 過濾器防止SQL注入 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java中struts2實現(xiàn)文件上傳下載功能實例解析
這篇文章主要介紹了java中struts2實現(xiàn)文件上傳下載功能的方法,以實例形式較為詳細的分析了struts2實現(xiàn)文件上傳下載功能的具體實現(xiàn)技巧與相關(guān)問題的解決方法,具有一定的參考借鑒價值,需要的朋友可以參考下2015-01-01
Spring中@RabbitHandler和@RabbitListener的區(qū)別詳析
@RabbitHandler是用于處理消息的方法注解,它與@RabbitListener注解一起使用,這篇文章主要給大家介紹了關(guān)于Spring中@RabbitHandler和@RabbitListener區(qū)別的相關(guān)資料,需要的朋友可以參考下2024-02-02
Java 并發(fā)編程學(xué)習(xí)筆記之Synchronized底層優(yōu)化
這篇文章主要介紹了Java 并發(fā)編程學(xué)習(xí)筆記之Synchronized底層優(yōu)化的相關(guān)資料,主要包含了重量級鎖,輕量級鎖,偏向鎖和其他優(yōu)化等方面,有需要的小伙伴可以參考下2016-05-05
快速解決commons-fileupload組件無法處理自定義head信息的bug
問題在于fileupload組件解析完自定義的head節(jié)點后,卻忘記傳遞到FileItemStreamImpl中了,稍作修訂,即可修正該bug2013-08-08
@Value設(shè)置默認(rèn)值后,獲取不到配置值的原因分析
這篇文章主要介紹了@Value設(shè)置默認(rèn)值后,獲取不到配置值的原因,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07

