SpringBoot實現(xiàn)防止XSS攻擊的示例詳解
XSS
跨站腳本工具(cross 斯特scripting),為不和層疊樣式表(cascading style sheets,CSS)的縮寫混淆,故將跨站腳本攻擊縮寫為XSS。惡意攻擊者往web頁面里插入惡意ScriptScript代碼,當(dāng)用戶瀏覽該頁之時,嵌入其中Web里面的Script代碼會被執(zhí)行,從而達(dá)到惡意攻擊用戶的目的。防止XSS攻擊簡單的預(yù)防就是對Request請求中的一些參數(shù)去掉一些比較敏感的腳本命令。原本是打算通過SpringMVC的HandlerInterceptor機制來實現(xiàn)的,通過獲取request然后對request中的參數(shù)進行修改,結(jié)果雖然值修改了,但在Controller中獲取的數(shù)值還是沒有修改的。沒辦法就是要Filter來完成。簡單來說就是創(chuàng)建一個新的HttpRequest類XssHttpServletRequestWrapper,然后重寫一些get方法(獲取參數(shù)時對參數(shù)進行XSS判斷預(yù)防)
流程梳理
包裝request->創(chuàng)建過濾器->添加過濾器
1.創(chuàng)建包裝request的類 XssHttpServletRequestWrapper
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sysware.framework.exceptions.SyswareRuntimeException;
import com.sysware.framework.file.service.impl.FileGridServiceImpl;
public class XssHttpServletRequestWraper extends HttpServletRequestWrapper {
private Logger log = LoggerFactory.getLogger(FileGridServiceImpl.class);
public XssHttpServletRequestWraper() {
super(null);
}
public XssHttpServletRequestWraper(HttpServletRequest httpservletrequest) {
super(httpservletrequest);
}
//過濾springmvc中的 @RequestParam 注解中的參數(shù)
public String[] getParameterValues(String s) {
String str[] = super.getParameterValues(s);
if (str == null) {
return null;
}
int i = str.length;
String as1[] = new String[i];
for (int j = 0; j < i; j++) {
//System.out.println("getParameterValues:"+str[j]);
as1[j] = cleanXSS(cleanSQLInject(str[j]));
}
log.info("XssHttpServletRequestWraper凈化后的請求為:==========" + as1);
return as1;
}
//過濾request.getParameter的參數(shù)
public String getParameter(String s) {
String s1 = super.getParameter(s);
if (s1 == null) {
return null;
} else {
String s2 = cleanXSS(cleanSQLInject(s1));
log.info("XssHttpServletRequestWraper凈化后的請求為:==========" + s2);
return s2;
}
}
//過濾請求體 json 格式的
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(inputHandlers(super.getInputStream ()).getBytes ());
return new ServletInputStream() {
@Override
public int read() throws IOException {
return bais.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) { }
};
}
public String inputHandlers(ServletInputStream servletInputStream){
StringBuilder sb = new StringBuilder();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(servletInputStream, Charset.forName("UTF-8")));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (servletInputStream != null) {
try {
servletInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return cleanXSS(sb.toString ());
}
public String cleanXSS(String src) {
String temp = src;
src = src.replaceAll("<", "<").replaceAll(">", ">");
src = src.replaceAll("\\(", "(").replaceAll("\\)", ")");
src = src.replaceAll("'", "");
src = src.replaceAll(";", "");
/**-----------------------start--------------------------*/
src = src.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
src = src.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41");
src = src.replaceAll("eval\\((.*)\\)", "");
src = src.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
// src = src.replaceAll("script", "");
// src = src.replaceAll("link", "");
// src = src.replaceAll("frame", "");
/**-----------------------end--------------------------*/
Pattern pattern = Pattern.compile("(eval\\((.*)\\)|script)",
Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(src);
src = matcher.replaceAll("");
pattern = Pattern.compile("[\\\"\\'][\\s]*javascript:(.*)[\\\"\\']",
Pattern.CASE_INSENSITIVE);
matcher = pattern.matcher(src);
src = matcher.replaceAll("\"\"");
// 增加腳本
src = src.replaceAll("script", "").replaceAll(";", "")
/*.replaceAll("\"", "").replaceAll("@", "")*/
.replaceAll("0x0d", "").replaceAll("0x0a", "");
// if (!temp.equals(src)) {
// // System.out.println("輸入信息存在xss攻擊!");
// // System.out.println("原始輸入信息-->" + temp);
// // System.out.println("處理后信息-->" + src);
//
// log.error("xss攻擊檢查:參數(shù)含有非法攻擊字符,已禁止繼續(xù)訪問??!");
// log.error("原始輸入信息-->" + temp);
//
// throw new SyswareRuntimeException("xss攻擊檢查:參數(shù)含有非法攻擊字符,已禁止繼續(xù)訪問??!");
// }
return src;
}
//輸出
public void outputMsgByOutputStream(HttpServletResponse response, String msg) throws IOException {
ServletOutputStream outputStream = response.getOutputStream(); //獲取輸出流
response.setHeader("content-type", "text/html;charset=UTF-8"); //通過設(shè)置響應(yīng)頭控制瀏覽器以UTF-8的編碼顯示數(shù)據(jù),如果不加這句話,那么瀏覽器顯示的將是亂碼
byte[] dataByteArr = msg.getBytes("UTF-8");// 將字符轉(zhuǎn)換成字節(jié)數(shù)組,指定以UTF-8編碼進行轉(zhuǎn)換
outputStream.write(dataByteArr);// 使用OutputStream流向客戶端輸出字節(jié)數(shù)組
}
// 需要增加通配,過濾大小寫組合
public String cleanSQLInject(String src) {
String lowSrc = src.toLowerCase();
String temp = src;
String lowSrcAfter = lowSrc.replaceAll(" insert ", "forbidI")
.replaceAll(" select ", "forbidS")
.replaceAll(" update ", "forbidU")
.replaceAll(" delete ", "forbidD").replaceAll(" and ", "forbidA")
.replaceAll(" or ", "forbidO").replace("'", "");
if (!lowSrcAfter.equals(lowSrc)) {
log.error("sql注入檢查:輸入信息存在SQL攻擊!");
log.error("原始輸入信息-->" + temp);
log.error("處理后信息-->" + lowSrc);
throw new SyswareRuntimeException("sql注入檢查:參數(shù)含有非法攻擊字符,已禁止繼續(xù)訪問?。?);
}
return src;
}
}注意:
getInputStream()方法的流處理,注解方式獲取數(shù)據(jù)貌似是根據(jù)這個流取得的數(shù)據(jù)。
因為super.getInputStream()流只允許讀取一次,所以在getInputStream()方法中處理完流數(shù)據(jù)后返回了一個新的ServletInputStream。另外替換方法里的替換規(guī)則,也可以根據(jù)實際業(yè)務(wù)需要進行調(diào)整。
2.創(chuàng)建過濾器 XssFilter
@Component
public class XssFilter implements Filter {
// 忽略權(quán)限檢查的url地址
private final String[] excludeUrls = new String[]{
"/api/item","api/document"
};
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) arg0;
HttpServletResponse response = (HttpServletResponse) arg1;
String pathInfo = req.getPathInfo() == null ? "" : req.getPathInfo();
//獲取請求url的后兩層
String url = req.getServletPath() + pathInfo;
//獲取請求你ip后的全部路徑
String uri = req.getRequestURI();
//注入xss過濾器實例
XssHttpServletRequestWraper reqW = new XssHttpServletRequestWraper(req);
//過濾掉不需要的Xss校驗的地址
for (String str : excludeUrls) {
if (uri.indexOf(str) >= 0) {
//過濾
arg2.doFilter(reqW, response);
return;
}
}
arg2.doFilter(arg0, response);
}
public void destroy() {
}
public void init(FilterConfig filterconfig1) throws ServletException {
}
}到此這篇關(guān)于SpringBoot實現(xiàn)防止XSS攻擊的示例詳解的文章就介紹到這了,更多相關(guān)SpringBoot防止XSS攻擊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java實現(xiàn)File轉(zhuǎn)換MultipartFile格式的例子
本文主要介紹了Java實現(xiàn)File轉(zhuǎn)換MultipartFile格式的例子,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
Spring?Boot?中的?@HystrixCommand?注解原理及使用方法
通過使用 @HystrixCommand 注解,我們可以輕松地實現(xiàn)對方法的隔離和監(jiān)控,從而提高系統(tǒng)的可靠性和穩(wěn)定性,本文介紹了Spring Boot 中的@HystrixCommand注解是什么,其原理以及如何使用,感興趣的朋友跟隨小編一起看看吧2023-07-07
Java Bean與Map之間相互轉(zhuǎn)化的實現(xiàn)方法
這篇文章主要介紹了Java Bean與Map之間相互轉(zhuǎn)化的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01

