利用过滤器将传参的特殊字符过滤掉
需要重写HttpServletRequestWrapper的getParameterValues方法;直接通过ServletRequest的设置属性值的方法修改参数是不行的,需要重新包装,才能真正更改值。
不想过滤的url通过设置intParam属性和isBlackURL方法来控制,这样可灵活配置多个。
/**过滤器过滤特殊字符**/
public class RequestParameterFilter implements Filter {
protected Logger log = LoggerFactory.getLogger(RequestParameterFilter.class);
/**无需过滤的传参集合*/
private List<String> excludeNames;
private final String[] NULL_STRING_ARRAY = new String[0];
private final String URL_SPLIT_PATTERN = "[, ;\r\n]";//逗号 空格 分号 换行
/**
* 不过滤的url
*/
private String[] blackListURLs = null;
public void destroy() {
}
private boolean isBlackURL(String currentURL) {
PathMatcher pathMatcher = new AntPathMatcher();
for (String blackURL : blackListURLs) {
if (pathMatcher.match(blackURL, currentURL)) {
log.debug("url filter : black url list matches : [{}] match [{}] break", blackURL, currentURL);
return true;
}
}
return false;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String currentURL = httpRequest.getServletPath();
if(!isBlackURL(currentURL)){
request = new HttpServletRequestWrapper2((HttpServletRequest) request);
}
chain.doFilter(request, response);
}
public void init(FilterConfig config) throws ServletException {
initConfig(config);
initExcludes();
}
/**不过滤参数*/
public void initExcludes(){
excludeNames = new ArrayList<String>();
excludeNames.add("password");
}
private void initConfig(FilterConfig filterConfig) {
String blackListURLStr = filterConfig.getInitParameter("blackListURL");
blackListURLs = strToArray(blackListURLStr);
}
private String[] strToArray(String urlStr) {
if (urlStr == null) {
return NULL_STRING_ARRAY;
}
String[] urlArray = urlStr.split(URL_SPLIT_PATTERN);
List<String> urlList = new ArrayList<String>();
for (String url : urlArray) {
url = url.trim();
if (url.length() == 0) {
continue;
}
urlList.add(url);
}
return urlList.toArray(NULL_STRING_ARRAY);
}
/**
* 该类继承之HttpServletRequestWrapper,并重写了getParameterValues方法。
*/
private class HttpServletRequestWrapper2 extends HttpServletRequestWrapper {
public HttpServletRequestWrapper2(HttpServletRequest request) {
super(request);
}
public String[] getParameterValues(String name) {
// 不过滤
if (excludeNames != null && excludeNames.contains(name)) {
return super.getParameterValues(name);
}
//需过滤
String param = filterParam(super.getParameterValues(name));
String[] str={param};
log.info("需过滤参数name[{}],value[{}],过滤后[{}]",new Object[]{name,super.getParameterValues(name),str[0]});
return str;
}
}
public String filterParam(String[] value) {
/**需过滤的特定字符*/
String specialCh[] = { "/", "\\", "<", ">", "%", "#", "'", "\"", "(", ")", ";" };
if (value != null && value.length > 0) {
String str = value[0];
// 将页面字符与所有特殊字符比对
for (int i = 0; i < specialCh.length; i++) {
if (str.indexOf(specialCh[i]) >= 0) {
str = str.replace(specialCh[i], "");
}
}
return str;
}
return null;
}
}
配置文件:
<filter>
<filter-name>baseFilter</filter-name>
<filter-class>com.filter.RequestParameterFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!-- 不过滤的url配置在此,注意/**,可以匹配多级目录,/*只可匹配一层目录(比如第一个可以匹配/a/b/c/d/e,/a/b/x等,而/*只能匹配/a/b/x,后面的多级目录无法匹配到) -->
<init-param>
<param-name>blackListURL</param-name>
<param-value>/a/b/**;/aa/**</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>baseFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>