From 9cda3cdf3c6e5088a2f05aa16e20e0c853f2c86b Mon Sep 17 00:00:00 2001 From: Stormeye Wu Date: Sat, 20 Apr 2019 11:01:18 +0800 Subject: [PATCH] =?UTF-8?q?[sql,xss=E9=98=B2=E6=8A=A4][=E6=96=B0=E5=A2=9E]?= =?UTF-8?q?:=E5=A2=9E=E5=8A=A0=E9=98=B2=E6=AD=A2sql=E6=B3=A8=E5=85=A5?= =?UTF-8?q?=E5=8F=8Axss=E6=94=BB=E5=87=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BodyReaderHttpServletRequestWrapper.java | 3 +- .../HttpServletRequestWrapperFilter.java | 35 ++++- .../XssHttpServletRequestWrapper.java | 122 ++++++++++++++++++ .../BodyReaderHttpServletRequestWrapper.java | 3 +- .../HttpServletRequestWrapperFilter.java | 35 ++++- .../XssHttpServletRequestWrapper.java | 122 ++++++++++++++++++ .../BodyReaderHttpServletRequestWrapper.java | 3 +- .../HttpServletRequestWrapperFilter.java | 30 ++++- .../XssHttpServletRequestWrapper.java | 122 ++++++++++++++++++ 9 files changed, 466 insertions(+), 9 deletions(-) create mode 100644 mallinkAdmin/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java create mode 100644 mallinkBApi/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java create mode 100644 mallinkCApi/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java diff --git a/mallinkAdmin/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java b/mallinkAdmin/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java index 46ee52e55..7be788b6e 100644 --- a/mallinkAdmin/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java +++ b/mallinkAdmin/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java @@ -3,10 +3,9 @@ package com.iformall.interceptor; import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; import java.io.*; -public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper { +public class BodyReaderHttpServletRequestWrapper extends XssHttpServletRequestWrapper { private final String body; public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException { diff --git a/mallinkAdmin/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java b/mallinkAdmin/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java index 644546097..aebf7d874 100644 --- a/mallinkAdmin/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java +++ b/mallinkAdmin/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java @@ -1,12 +1,20 @@ package com.iformall.interceptor; import com.iformall.utils.UrlCheck; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.util.Arrays; public class HttpServletRequestWrapperFilter implements Filter { + private static final Logger logger = LoggerFactory.getLogger(HttpServletRequestWrapperFilter.class); + // 多个跨域域名设置 + // public static final String[] ALLOW_DOMAIN = {"https://admin.malls.iformall.com"}; + @Override public void init(FilterConfig filterConfig) throws ServletException { @@ -17,6 +25,31 @@ public class HttpServletRequestWrapperFilter implements Filter { throws IOException, ServletException { ServletRequest requestWrapper = null; + /* // 跨域访问 + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse res = (HttpServletResponse) response; + String originHeader = req.getHeader("Origin"); + + if (Arrays.asList(ALLOW_DOMAIN).contains(originHeader)) { + //通过在响应 header 中设置 ‘*’ 来允许来自所有域的跨域请求访问。 + res.setHeader("Access-Control-Allow-Origin", originHeader); + //通过对 Credentials 参数的设置,就可以保持跨域 Ajax 时的 Cookie + //设置了Allow-Credentials,Allow-Origin就不能为*,需要指明具体的url域 + res.setHeader("Access-Control-Allow-Credentials", "true"); + //请求方式 + res.setHeader("Access-Control-Allow-Methods", "*"); + //(预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被缓存多久 + res.setHeader("Access-Control-Max-Age", "86400"); + //首部字段用于预检请求的响应。其指明了实际请求中允许携带的首部字段 + //res.setHeader("Access-Control-Allow-Headers", "*"); + res.setHeader("Access-Control-Allow-Headers", + "Timestamp,Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token,Access-Control-Allow-Headers"); + } + */ + + //sql,xss过滤 + XssHttpServletRequestWrapper xssHttpServletRequestWrapper = new XssHttpServletRequestWrapper((HttpServletRequest)request); + if (request instanceof HttpServletRequest) { String url = ((HttpServletRequest) request).getRequestURI(); if (!UrlCheck.checkUrl(url)) { @@ -24,7 +57,7 @@ public class HttpServletRequestWrapperFilter implements Filter { } } if (null == requestWrapper) { - chain.doFilter(request, response); + chain.doFilter(xssHttpServletRequestWrapper, response); } else { chain.doFilter(requestWrapper, response); } diff --git a/mallinkAdmin/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java b/mallinkAdmin/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java new file mode 100644 index 000000000..0ee75b20a --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java @@ -0,0 +1,122 @@ +package com.iformall.interceptor; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * 防止sql注入,xss攻击 + * 前端可以对输入信息做预处理,后端也可以做处理。 + */ +public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { + private final Logger log = LoggerFactory.getLogger(getClass()); + private static String key = "and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+"; + private static Set notAllowedKeyWords = new HashSet(0); + private static String replacedString="INVALID"; + static { + String keyStr[] = key.split("\\|"); + for (String str : keyStr) { + notAllowedKeyWords.add(str); + } + } + + private String currentUrl; + + public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) { + super(servletRequest); + currentUrl = servletRequest.getRequestURI(); + } + + + /**覆盖getParameter方法,将参数名和参数值都做xss过滤。 + * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取 + * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖 + */ + @Override + public String getParameter(String parameter) { + String value = super.getParameter(parameter); + if (value == null) { + return null; + } + return cleanXSS(value); + } + @Override + public String[] getParameterValues(String parameter) { + String[] values = super.getParameterValues(parameter); + if (values == null) { + return null; + } + int count = values.length; + String[] encodedValues = new String[count]; + for (int i = 0; i < count; i++) { + encodedValues[i] = cleanXSS(values[i]); + } + return encodedValues; + } + @Override + public Map getParameterMap(){ + Map values=super.getParameterMap(); + if (values == null) { + return null; + } + Map result=new HashMap<>(); + for(String key:values.keySet()){ + String encodedKey=cleanXSS(key); + int count=values.get(key).length; + String[] encodedValues = new String[count]; + for (int i = 0; i < count; i++){ + encodedValues[i]=cleanXSS(values.get(key)[i]); + } + result.put(encodedKey,encodedValues); + } + return result; + } + /** + * 覆盖getHeader方法,将参数名和参数值都做xss过滤。 + * 如果需要获得原始的值,则通过super.getHeaders(name)来获取 + * getHeaderNames 也可能需要覆盖 + */ + @Override + public String getHeader(String name) { + String value = super.getHeader(name); + if (value == null) { + return null; + } + return cleanXSS(value); + } + + private String cleanXSS(String valueP) { + // You'll need to remove the spaces from the html entities below + String value = valueP.replaceAll("<", "<").replaceAll(">", ">"); + 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("script", ""); + value = cleanSqlKeyWords(value); + return value; + } + + private String cleanSqlKeyWords(String value) { + String paramValue = value; + for (String keyword : notAllowedKeyWords) { + if (paramValue.length() > keyword.length() + 4 + && (paramValue.contains(" "+keyword)||paramValue.contains(keyword+" ")||paramValue.contains(" "+keyword+" "))) { + paramValue = StringUtils.replace(paramValue, keyword, replacedString); + log.error(this.currentUrl + "已被过滤,因为参数中包含不允许sql的关键词(" + keyword + + ")"+";参数:"+value+";过滤后的参数:"+paramValue); + } + } + return paramValue; + } + +} diff --git a/mallinkBApi/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java b/mallinkBApi/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java index 46ee52e55..7be788b6e 100644 --- a/mallinkBApi/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java +++ b/mallinkBApi/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java @@ -3,10 +3,9 @@ package com.iformall.interceptor; import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; import java.io.*; -public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper { +public class BodyReaderHttpServletRequestWrapper extends XssHttpServletRequestWrapper { private final String body; public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException { diff --git a/mallinkBApi/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java b/mallinkBApi/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java index ed6f301c9..bc1aa1c95 100644 --- a/mallinkBApi/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java +++ b/mallinkBApi/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java @@ -1,12 +1,18 @@ package com.iformall.interceptor; import com.iformall.utils.UrlCheck; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; public class HttpServletRequestWrapperFilter implements Filter { + private static final Logger logger = LoggerFactory.getLogger(HttpServletRequestWrapperFilter.class); + // 多个跨域域名设置 + // public static final String[] ALLOW_DOMAIN = {"https://admin.malls.iformall.com"}; + @Override public void init(FilterConfig filterConfig) throws ServletException { @@ -17,14 +23,41 @@ public class HttpServletRequestWrapperFilter implements Filter { throws IOException, ServletException { ServletRequest requestWrapper = null; + + /* // 跨域访问 + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse res = (HttpServletResponse) response; + String originHeader = req.getHeader("Origin"); + + if (Arrays.asList(ALLOW_DOMAIN).contains(originHeader)) { + //通过在响应 header 中设置 ‘*’ 来允许来自所有域的跨域请求访问。 + res.setHeader("Access-Control-Allow-Origin", originHeader); + //通过对 Credentials 参数的设置,就可以保持跨域 Ajax 时的 Cookie + //设置了Allow-Credentials,Allow-Origin就不能为*,需要指明具体的url域 + res.setHeader("Access-Control-Allow-Credentials", "true"); + //请求方式 + res.setHeader("Access-Control-Allow-Methods", "*"); + //(预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被缓存多久 + res.setHeader("Access-Control-Max-Age", "86400"); + //首部字段用于预检请求的响应。其指明了实际请求中允许携带的首部字段 + //res.setHeader("Access-Control-Allow-Headers", "*"); + res.setHeader("Access-Control-Allow-Headers", + "Timestamp,Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token,Access-Control-Allow-Headers"); + } + */ + + //sql,xss过滤 + XssHttpServletRequestWrapper xssHttpServletRequestWrapper = new XssHttpServletRequestWrapper((HttpServletRequest)request); + if (request instanceof HttpServletRequest) { String url = ((HttpServletRequest) request).getRequestURI(); if (!UrlCheck.checkUrl(url)) { requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) request); } } + if (null == requestWrapper) { - chain.doFilter(request, response); + chain.doFilter(xssHttpServletRequestWrapper, response); } else { chain.doFilter(requestWrapper, response); } diff --git a/mallinkBApi/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java b/mallinkBApi/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java new file mode 100644 index 000000000..0ee75b20a --- /dev/null +++ b/mallinkBApi/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java @@ -0,0 +1,122 @@ +package com.iformall.interceptor; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * 防止sql注入,xss攻击 + * 前端可以对输入信息做预处理,后端也可以做处理。 + */ +public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { + private final Logger log = LoggerFactory.getLogger(getClass()); + private static String key = "and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+"; + private static Set notAllowedKeyWords = new HashSet(0); + private static String replacedString="INVALID"; + static { + String keyStr[] = key.split("\\|"); + for (String str : keyStr) { + notAllowedKeyWords.add(str); + } + } + + private String currentUrl; + + public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) { + super(servletRequest); + currentUrl = servletRequest.getRequestURI(); + } + + + /**覆盖getParameter方法,将参数名和参数值都做xss过滤。 + * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取 + * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖 + */ + @Override + public String getParameter(String parameter) { + String value = super.getParameter(parameter); + if (value == null) { + return null; + } + return cleanXSS(value); + } + @Override + public String[] getParameterValues(String parameter) { + String[] values = super.getParameterValues(parameter); + if (values == null) { + return null; + } + int count = values.length; + String[] encodedValues = new String[count]; + for (int i = 0; i < count; i++) { + encodedValues[i] = cleanXSS(values[i]); + } + return encodedValues; + } + @Override + public Map getParameterMap(){ + Map values=super.getParameterMap(); + if (values == null) { + return null; + } + Map result=new HashMap<>(); + for(String key:values.keySet()){ + String encodedKey=cleanXSS(key); + int count=values.get(key).length; + String[] encodedValues = new String[count]; + for (int i = 0; i < count; i++){ + encodedValues[i]=cleanXSS(values.get(key)[i]); + } + result.put(encodedKey,encodedValues); + } + return result; + } + /** + * 覆盖getHeader方法,将参数名和参数值都做xss过滤。 + * 如果需要获得原始的值,则通过super.getHeaders(name)来获取 + * getHeaderNames 也可能需要覆盖 + */ + @Override + public String getHeader(String name) { + String value = super.getHeader(name); + if (value == null) { + return null; + } + return cleanXSS(value); + } + + private String cleanXSS(String valueP) { + // You'll need to remove the spaces from the html entities below + String value = valueP.replaceAll("<", "<").replaceAll(">", ">"); + 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("script", ""); + value = cleanSqlKeyWords(value); + return value; + } + + private String cleanSqlKeyWords(String value) { + String paramValue = value; + for (String keyword : notAllowedKeyWords) { + if (paramValue.length() > keyword.length() + 4 + && (paramValue.contains(" "+keyword)||paramValue.contains(keyword+" ")||paramValue.contains(" "+keyword+" "))) { + paramValue = StringUtils.replace(paramValue, keyword, replacedString); + log.error(this.currentUrl + "已被过滤,因为参数中包含不允许sql的关键词(" + keyword + + ")"+";参数:"+value+";过滤后的参数:"+paramValue); + } + } + return paramValue; + } + +} diff --git a/mallinkCApi/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java b/mallinkCApi/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java index 46ee52e55..7be788b6e 100644 --- a/mallinkCApi/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java +++ b/mallinkCApi/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java @@ -3,10 +3,9 @@ package com.iformall.interceptor; import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; import java.io.*; -public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper { +public class BodyReaderHttpServletRequestWrapper extends XssHttpServletRequestWrapper { private final String body; public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException { diff --git a/mallinkCApi/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java b/mallinkCApi/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java index 244517814..5b5d5b971 100644 --- a/mallinkCApi/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java +++ b/mallinkCApi/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java @@ -10,6 +10,8 @@ import java.io.IOException; public class HttpServletRequestWrapperFilter implements Filter { private final Logger logger = LoggerFactory.getLogger(this.getClass()); + // 多个跨域域名设置 + // public static final String[] ALLOW_DOMAIN = {"https://admin.malls.iformall.com"}; @Override public void init(FilterConfig filterConfig) throws ServletException { @@ -21,6 +23,32 @@ public class HttpServletRequestWrapperFilter implements Filter { logger.debug("doFilter start"); long start = System.currentTimeMillis(); ServletRequest requestWrapper = null; + + /* // 跨域访问 + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse res = (HttpServletResponse) response; + String originHeader = req.getHeader("Origin"); + + if (Arrays.asList(ALLOW_DOMAIN).contains(originHeader)) { + //通过在响应 header 中设置 ‘*’ 来允许来自所有域的跨域请求访问。 + res.setHeader("Access-Control-Allow-Origin", originHeader); + //通过对 Credentials 参数的设置,就可以保持跨域 Ajax 时的 Cookie + //设置了Allow-Credentials,Allow-Origin就不能为*,需要指明具体的url域 + res.setHeader("Access-Control-Allow-Credentials", "true"); + //请求方式 + res.setHeader("Access-Control-Allow-Methods", "*"); + //(预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被缓存多久 + res.setHeader("Access-Control-Max-Age", "86400"); + //首部字段用于预检请求的响应。其指明了实际请求中允许携带的首部字段 + //res.setHeader("Access-Control-Allow-Headers", "*"); + res.setHeader("Access-Control-Allow-Headers", + "Timestamp,Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token,Access-Control-Allow-Headers"); + } + */ + + //sql,xss过滤 + XssHttpServletRequestWrapper xssHttpServletRequestWrapper = new XssHttpServletRequestWrapper((HttpServletRequest)request); + if (request instanceof HttpServletRequest) { String url = ((HttpServletRequest) request).getRequestURI(); if (!UrlCheck.checkUrl(url)) { @@ -28,7 +56,7 @@ public class HttpServletRequestWrapperFilter implements Filter { } } if (null == requestWrapper) { - chain.doFilter(request, response); + chain.doFilter(xssHttpServletRequestWrapper, response); } else { chain.doFilter(requestWrapper, response); } diff --git a/mallinkCApi/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java b/mallinkCApi/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java new file mode 100644 index 000000000..0ee75b20a --- /dev/null +++ b/mallinkCApi/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java @@ -0,0 +1,122 @@ +package com.iformall.interceptor; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * 防止sql注入,xss攻击 + * 前端可以对输入信息做预处理,后端也可以做处理。 + */ +public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { + private final Logger log = LoggerFactory.getLogger(getClass()); + private static String key = "and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+"; + private static Set notAllowedKeyWords = new HashSet(0); + private static String replacedString="INVALID"; + static { + String keyStr[] = key.split("\\|"); + for (String str : keyStr) { + notAllowedKeyWords.add(str); + } + } + + private String currentUrl; + + public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) { + super(servletRequest); + currentUrl = servletRequest.getRequestURI(); + } + + + /**覆盖getParameter方法,将参数名和参数值都做xss过滤。 + * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取 + * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖 + */ + @Override + public String getParameter(String parameter) { + String value = super.getParameter(parameter); + if (value == null) { + return null; + } + return cleanXSS(value); + } + @Override + public String[] getParameterValues(String parameter) { + String[] values = super.getParameterValues(parameter); + if (values == null) { + return null; + } + int count = values.length; + String[] encodedValues = new String[count]; + for (int i = 0; i < count; i++) { + encodedValues[i] = cleanXSS(values[i]); + } + return encodedValues; + } + @Override + public Map getParameterMap(){ + Map values=super.getParameterMap(); + if (values == null) { + return null; + } + Map result=new HashMap<>(); + for(String key:values.keySet()){ + String encodedKey=cleanXSS(key); + int count=values.get(key).length; + String[] encodedValues = new String[count]; + for (int i = 0; i < count; i++){ + encodedValues[i]=cleanXSS(values.get(key)[i]); + } + result.put(encodedKey,encodedValues); + } + return result; + } + /** + * 覆盖getHeader方法,将参数名和参数值都做xss过滤。 + * 如果需要获得原始的值,则通过super.getHeaders(name)来获取 + * getHeaderNames 也可能需要覆盖 + */ + @Override + public String getHeader(String name) { + String value = super.getHeader(name); + if (value == null) { + return null; + } + return cleanXSS(value); + } + + private String cleanXSS(String valueP) { + // You'll need to remove the spaces from the html entities below + String value = valueP.replaceAll("<", "<").replaceAll(">", ">"); + 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("script", ""); + value = cleanSqlKeyWords(value); + return value; + } + + private String cleanSqlKeyWords(String value) { + String paramValue = value; + for (String keyword : notAllowedKeyWords) { + if (paramValue.length() > keyword.length() + 4 + && (paramValue.contains(" "+keyword)||paramValue.contains(keyword+" ")||paramValue.contains(" "+keyword+" "))) { + paramValue = StringUtils.replace(paramValue, keyword, replacedString); + log.error(this.currentUrl + "已被过滤,因为参数中包含不允许sql的关键词(" + keyword + + ")"+";参数:"+value+";过滤后的参数:"+paramValue); + } + } + return paramValue; + } + +}