利用過濾器將傳參的特殊字符過濾掉
需要重寫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>