使用springMVC通過(guò)Filter實(shí)現(xiàn)防止xss注入
springMVC Filter防止xss注入
跨站腳本工具(cross 斯特scripting),為不和層疊樣式表(cascading style sheets,CSS)的縮寫(xiě)混淆,故將跨站腳本攻擊縮寫(xiě)為XSS。
惡意攻擊者往web頁(yè)面里插入惡意scriptScript代碼,當(dāng)用戶瀏覽該頁(yè)之時(shí),嵌入其中Web里面的Script代碼會(huì)被執(zhí)行,從而達(dá)到惡意攻擊用戶的目的。
防止XSS攻擊簡(jiǎn)單的預(yù)防就是對(duì)Request請(qǐng)求中的一些參數(shù)去掉一些比較敏感的腳本命令。
原本是打算通過(guò)springMVC的HandlerInterceptor機(jī)制來(lái)實(shí)現(xiàn)的,通過(guò)獲取request然后對(duì)request中的參數(shù)進(jìn)行修改,結(jié)果雖然值修改了,但在Controller中獲取的數(shù)值還是沒(méi)有修改的。沒(méi)辦法就是要Filter來(lái)完成。
簡(jiǎn)單來(lái)說(shuō)就是創(chuàng)建一個(gè)新的httpRequest類XsslHttpServletRequestWrapper,然后重寫(xiě)一些get方法(獲取參數(shù)時(shí)對(duì)參數(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代碼的過(guò)濾是在XsslHttpServletRequestWrapper中實(shí)現(xiàn)的,主要是覆蓋實(shí)現(xiàn)了getParameter,getParameterValues,getHeader這幾個(gè)方法,然后對(duì)獲取的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的語(yǔ)句,轉(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); } /** * 過(guò)濾特殊字符 */ 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過(guò)濾請(qǐng)求的參數(shù):Content-Type為 json(application/json)
SpringMVC 對(duì)于application/json 轉(zhuǎn)換處理說(shuō)明:
spring mvc默認(rèn)使用MappingJackson2HttpMessageConverter轉(zhuǎn)換器,
而它是使用jackson來(lái)序列化對(duì)象的,如果我們能 將jackson的序列化和反序列化過(guò)程修改,加入過(guò)濾xss代碼,并將其注冊(cè)到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 配置對(duì)象:
@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(); // 注冊(cè)自定義的序列化和反序列化器 mapper.registerModule(module); MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(mapper); converters.add(converter); } }
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot中@RestControllerAdvice注解實(shí)現(xiàn)全局異常處理類
這篇文章主要介紹了SpringBoot中@RestControllerAdvice注解全局異常處理類,springboot中使用@RestControllerAdvice注解,完成優(yōu)雅的全局異常處理類,可以針對(duì)所有異常類型先進(jìn)行通用處理后再對(duì)特定異常類型進(jìn)行不同的處理操作,需要的朋友可以參考下2024-01-01SpringBoot使用Netty實(shí)現(xiàn)遠(yuǎn)程調(diào)用的示例
這篇文章主要介紹了SpringBoot使用Netty實(shí)現(xiàn)遠(yuǎn)程調(diào)用的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10java高并發(fā)ThreadPoolExecutor類解析線程池執(zhí)行流程
這篇文章主要為大家介紹了java高并發(fā)ThreadPoolExecutor類解析線程池執(zhí)行流程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09java對(duì)xml節(jié)點(diǎn)屬性的增刪改查實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇java對(duì)xml節(jié)點(diǎn)屬性的增刪改查實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-10-10java網(wǎng)上圖書(shū)商城(5)購(gòu)物車模塊2
這篇文章主要為大家詳細(xì)介紹了java網(wǎng)上圖書(shū)商城,購(gòu)物車模塊第二篇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12Java開(kāi)發(fā)微信公眾號(hào)接收和被動(dòng)回復(fù)普通消息
這篇文章主要介紹了Java開(kāi)發(fā)微信公眾號(hào)接收和被動(dòng)回復(fù)普通消息的相關(guān)資料,需要的朋友可以參考下2016-01-01