使用springMVC通過Filter實(shí)現(xiàn)防止xss注入
springMVC Filter防止xss注入
跨站腳本工具(cross 斯特scripting),為不和層疊樣式表(cascading style sheets,CSS)的縮寫混淆,故將跨站腳本攻擊縮寫為XSS。
惡意攻擊者往web頁面里插入惡意scriptScript代碼,當(dāng)用戶瀏覽該頁之時(shí),嵌入其中Web里面的Script代碼會(huì)被執(zhí)行,從而達(dá)到惡意攻擊用戶的目的。
防止XSS攻擊簡單的預(yù)防就是對Request請求中的一些參數(shù)去掉一些比較敏感的腳本命令。
原本是打算通過springMVC的HandlerInterceptor機(jī)制來實(shí)現(xiàn)的,通過獲取request然后對request中的參數(shù)進(jìn)行修改,結(jié)果雖然值修改了,但在Controller中獲取的數(shù)值還是沒有修改的。沒辦法就是要Filter來完成。
簡單來說就是創(chuàng)建一個(gè)新的httpRequest類XsslHttpServletRequestWrapper,然后重寫一些get方法(獲取參數(shù)時(shí)對參數(shù)進(jìn)行XSS判斷預(yù)防)。
@WebFilter(filterName="xssMyfilter",urlPatterns="/*")
public class MyXssFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
XsslHttpServletRequestWrapper xssRequest = new XsslHttpServletRequestWrapper((HttpServletRequest)request);
chain.doFilter(xssRequest , response);
}
@Override
public void destroy() {
}
}
XSS代碼的過濾是在XsslHttpServletRequestWrapper中實(shí)現(xiàn)的,主要是覆蓋實(shí)現(xiàn)了getParameter,getParameterValues,getHeader這幾個(gè)方法,然后對獲取的value值進(jìn)行XSS處理。
public class XsslHttpServletRequestWrapper extends HttpServletRequestWrapper {
HttpServletRequest xssRequest = null;
public XsslHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
xssRequest = request;
}
@Override
public String getParameter(String name) {
String value = super.getParameter(replaceXSS(name));
if (value != null) {
value = replaceXSS(value);
}
return value;
}
@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(replaceXSS(name));
if(values != null && values.length > 0){
for(int i =0; i< values.length ;i++){
values[i] = replaceXSS(values[i]);
}
}
return values;
}
@Override
public String getHeader(String name) {
String value = super.getHeader(replaceXSS(name));
if (value != null) {
value = replaceXSS(value);
}
return value;
}
/**
* 去除待帶script、src的語句,轉(zhuǎn)義替換后的value值
*/
public static String replaceXSS(String value) {
if (value != null) {
try{
value = value.replace("+","%2B"); //'+' replace to '%2B'
value = URLDecoder.decode(value, "utf-8");
}catch(UnsupportedEncodingException e){
}catch(IllegalArgumentException e){
}
// Avoid null characters
value = value.replaceAll("\0", "");
// Avoid anything between script tags
Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid anything in a src='...' type of expression
scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Remove any lonesome </script> tag
scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// Remove any lonesome <script ...> tag
scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid eval(...) expressions
scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid expression(...) expressions
scriptPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid javascript:... expressions
scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid alert:... expressions
scriptPattern = Pattern.compile("alert", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid οnlοad= expressions
scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("vbscript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
}
return filter(value);
}
/**
* 過濾特殊字符
*/
public static String filter(String value) {
if (value == null) {
return null;
}
StringBuffer result = new StringBuffer(value.length());
for (int i=0; i<value.length(); ++i) {
switch (value.charAt(i)) {
case '<':
result.append("<");
break;
case '>':
result.append(">");
break;
case '"':
result.append(""");
break;
case '\'':
result.append("'");
break;
case '%':
result.append("%");
break;
case ';':
result.append(";");
break;
case '(':
result.append("(");
break;
case ')':
result.append(")");
break;
case '&':
result.append("&");
break;
case '+':
result.append("+");
break;
default:
result.append(value.charAt(i));
break;
}
}
return result.toString();
}
}
SpringMVC 防止XSS 工具(常規(guī)方式)
要求:
xss過濾請求的參數(shù):Content-Type為 json(application/json)
SpringMVC 對于application/json 轉(zhuǎn)換處理說明:
spring mvc默認(rèn)使用MappingJackson2HttpMessageConverter轉(zhuǎn)換器,
而它是使用jackson來序列化對象的,如果我們能 將jackson的序列化和反序列化過程修改,加入過濾xss代碼,并將其注冊到MappingJackson2HttpMessageConverter中
具體實(shí)現(xiàn)功能代碼:
import java.io.IOException;
import org.apache.commons.text.StringEscapeUtils;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
/**
* 反序列化
*
*/
public class XssDefaultJsonDeserializer extends StdDeserializer<String> {
public XssDefaultJsonDeserializer(){
this(null);
}
public XssDefaultJsonDeserializer(Class<String> vc) {
super(vc);
}
@Override
public String deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
// TODO Auto-generated method stub
//return StringEscapeUtils.escapeEcmaScript(jsonParser.getText());
return StringEscapeUtils.unescapeHtml4(jsonParser.getText());
}
}
SpringMVC 配置對象:
@Configuration
@EnableWebMvc
public class SpingMVCConfig extends WebMvcConfigurerAdapter {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
super.configureMessageConverters(converters);
// TODO Auto-generated method stub
SimpleModule module = new SimpleModule();
// 反序列化
module.addDeserializer(String.class, new XssDefaultJsonDeserializer());
// 序列化
module.addSerializer(String.class, new XssDefaultJsonSerializer());
ObjectMapper mapper = Jackson2ObjectMapperBuilder.json().build();
// 注冊自定義的序列化和反序列化器
mapper.registerModule(module);
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(mapper);
converters.add(converter);
}
}
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
將springboot項(xiàng)目生成可依賴的jar并引入到項(xiàng)目中的方法
SpringBoot項(xiàng)目默認(rèn)打包的是可運(yùn)行jar包,也可以打包成不可運(yùn)行的jar包,本文給大家介紹將springboot項(xiàng)目生成可依賴的jar并引入到項(xiàng)目中的方法,感興趣的朋友一起看看吧2023-11-11
IntelliJ IDEA 使用經(jīng)驗(yàn)總結(jié)(推薦)
這篇文章主要介紹了IntelliJ IDEA 使用經(jīng)驗(yàn)總結(jié),非常不錯(cuò),具有參考價(jià)值,需要的朋友可以參考下2018-02-02
SpringBoot應(yīng)用部署到外置Tomcat的實(shí)現(xiàn)
SpringBoot內(nèi)置tomcat使用很方便,本文主要介紹了SpringBoot應(yīng)用部署到外置Tomcat的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-07-07
詳解spring項(xiàng)目中如何動(dòng)態(tài)刷新bean
這篇文章主要為大家介紹了詳解spring項(xiàng)目中如何動(dòng)態(tài)刷新bean,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
Java 實(shí)戰(zhàn)范例之進(jìn)銷存管理系統(tǒng)的實(shí)現(xiàn)
讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+vue+Springboot+ssm+mysql+maven+redis實(shí)現(xiàn)一個(gè)前后端分離的進(jìn)銷存管理系統(tǒng),大家可以在過程中查缺補(bǔ)漏,提升水平2021-11-11

