1.过滤器代码
1
package com.ufgov.util;
2
3
import java.io.IOException;
4
5
import javax.servlet.Filter;
6
import javax.servlet.FilterChain;
7
import javax.servlet.FilterConfig;
8
import javax.servlet.ServletException;
9
import javax.servlet.ServletRequest;
10
import javax.servlet.ServletResponse;
11
import javax.servlet.http.HttpServletRequest;
12
13
/**
14
*特殊字符过滤器
15
*可以过滤xss和sql注入的关键字
16
*/
17
public class CharacterFilter implements Filter {
18
19
public void destroy() {
20
}
21
22
public void doFilter(ServletRequest req, ServletResponse res,
23
FilterChain chain) throws IOException, ServletException {
24
HttpServletRequest request = (HttpServletRequest) req;
25
TsRequest wrapRequest = new TsRequest(request,
26
request.getParameterMap());
27
chain.doFilter(wrapRequest, res);
28
}
29
30
public void init(FilterConfig arg0) throws ServletException {
31
}
32
}
2.具体的实现
1
package com.ufgov.util;
2
3
import com.google.gson.JsonParseException;
4
import com.google.gson.JsonParser;
5
import com.ufgov.entity.SysRole;
6
import com.ufgov.entity.SysUserInfo;
7
import net.sf.json.JSONArray;
8
import net.sf.json.JSONObject;
9
import org.apache.commons.lang3.StringUtils;
10
11
import javax.servlet.ServletInputStream;
12
import javax.servlet.ServletRequest;
13
import javax.servlet.http.HttpServletRequest;
14
import javax.servlet.http.HttpServletRequestWrapper;
15
import java.io.*;
16
import java.lang.reflect.Method;
17
import java.nio.charset.Charset;
18
import java.util.*;
19
import java.util.Map.Entry;
20
21
/**
22
*封装的请求处理特殊字符
23
*配合过滤器处理特殊字符
24
*/
25
public class TsRequest extends HttpServletRequestWrapper {
26
27
// 非法字符集 转成空
28
private static String[] illegalArr = { "script", "alert", "expression", "iframe", "prompt", "\\\\u", "onerror",
29
"onmousemove", "onafterprint", "onbeforeprint", "onbeforeunload", "onerror", "onhaschange", "onload",
30
"onmessage", "onoffline", "ononline", "onpagehide", "onpageshow", "onpopstate", "onredo", "onresize",
31
"onstorage", "onundo", "onunload", "onblur", "onchange", "oncontextmenu", "onfocus", "onformchange",
32
"onforminput", "oninput", "oninvalid", "onreset", "onselect", "onsubmit", "onkeydown", "onkeypress",
33
"onkeyup", "onclick", "ondblclick", "ondrag", "ondragend", "ondragenter", "ondragleave", "ondragover",
34
"ondragstart", "ondrop", "onmousedown", "onmousemove", "onmouseout", "onmouseover", "onmouseup",
35
"onmousewheel", "onscroll", "onabort", "oncanplay", "oncanplaythrough", "ondurationchange", "onemptied",
36
"onended", "onerror", "onloadeddata", "onloadedmetadata", "onloadstart", "onpause", "onplay", "onplaying",
37
"onprogress", "onratechange", "onreadystatechange", "onseeked", "onseeking", "onstalled", "onsuspend",
38
"ontimeupdate", "onvolumechange", "onwaiting" };
39
//html转义
40
private static Map<String, String> illegalMap = new HashMap<String, String>() {
41
{
42
put("<", "<");
43
put(">", ">");
44
put("'", "'");
45
put("\"", """);
46
put("/", "/");
47
put("\\\\", "\");
48
put("\\)", ")");//)
49
put("\\(", "(");//(
50
put(";", ";");//;
51
put("\\[", "【");//[
52
put("\\]", "】");//\
53
}
54
};
55
private Map params;
56
private final String bodyParam;
57
public TsRequest(HttpServletRequest request, Map newParams) {
58
super(request);
59
this.params = newParams;
60
String contentType = request.getContentType();
61
// System.out.println(contentType);
62
//不再过滤文件上传
63
CharSequence cs = "multipart/form-data";
64
if(contentType!=null && contentType.toLowerCase().contains(cs)){
65
this.bodyParam = null;
66
}else {
67
this.bodyParam = getBodyString(request);
68
}
69
}
70
71
/**
72
* 从流中获取请求Body
73
*
74
* @param request
75
* @return
76
*/
77
private static String getBodyString(ServletRequest request) {
78
StringBuilder sb = new StringBuilder();
79
InputStream inputStream = null;
80
BufferedReader reader = null;
81
try {
82
inputStream = request.getInputStream();
83
reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
84
String line;
85
while ((line = reader.readLine()) != null) {
86
sb.append(line);
87
}
88
} catch (IOException e) {
89
e.printStackTrace();
90
} finally {
91
if (inputStream != null) {
92
try {
93
inputStream.close();
94
} catch (IOException e) {
95
e.printStackTrace();
96
}
97
}
98
if (reader != null) {
99
try {
100
reader.close();
101
} catch (IOException e) {
102
e.printStackTrace();
103
}
104
}
105
}
106
return sb.toString();
107
}
108
/**
109
* getReader和getInputStream解决在parameter中无法获取参数的过滤
110
*
111
* @return
112
* @throws IOException
113
*/
114
@Override
115
public BufferedReader getReader() throws IOException {
116
return new BufferedReader(new InputStreamReader(getInputStream()));
117
}
118
119
//排除前端的json字符串中,json用来处理json串的特殊字符.
120
@Override
121
public ServletInputStream getInputStream() throws IOException {
122
if(bodyParam == null){
123
return super.getInputStream();
124
}
125
String strCopy = bodyParam.trim();
126
String newStr;
127
char firstChar = strCopy.toCharArray()[0];
128
if(firstChar == '{' && isGoodJson(strCopy)){//JsonObject
129
JSONObject jsonObject = JSONObject.fromObject(strCopy);
130
// jsonObject =
131
jsonCheck(jsonObject);
132
newStr = jsonObject.toString();
133
}else if(firstChar == '[' && isGoodJson(strCopy)){//JsonArray
134
JSONArray jsonArray = JSONArray.fromObject(strCopy);
135
JSONArray tempArray = new JSONArray();
136
for (int i = 0; i < jsonArray.size(); i++) {
137
JSONObject jsonObject = (JSONObject)jsonArray.get(i);
138
jsonCheck(jsonObject);
139
tempArray.add(jsonObject);
140
}
141
newStr = tempArray.toString();
142
}else{
143
newStr = charFilter(bodyParam);
144
}
145
final ByteArrayInputStream bais = new ByteArrayInputStream(newStr.getBytes(Charset.forName("UTF-8")));
146
147
return new ServletInputStream() {
148
@Override
149
public int read() throws IOException {
150
return bais.read();
151
}
152
};
153
}
154
155
/**
156
* 检查json中的值是否需要过滤.key值未判断
157
* @param jsonObject
158
*/
159
private void jsonCheck(JSONObject jsonObject){
160
// JSONObject tempObj = new JSONObject();
161
for (Object object : jsonObject.entrySet()) {
162
Entry entry = (Entry)object;
163
String key = (String)entry.getKey();
164
Object obj = entry.getValue();
165
if(obj instanceof String){
166
String val = charFilter((String)obj);
167
jsonObject.put(key,val);
168
}else if(obj instanceof JSONObject){
169
// jsonObject.put(key,jsonCheck((JSONObject)obj));
170
jsonCheck((JSONObject)obj);
171
jsonObject.put(key,obj);
172
}else if(obj instanceof JSONArray){
173
JSONArray arr = (JSONArray)obj;
174
JSONArray tempArr = new JSONArray();
175
for (int i = 0; i < arr.size(); i++) {
176
Object tempObj = arr.get(i);
177
if(tempObj instanceof JSONObject){
178
jsonCheck((JSONObject)tempObj);
179
tempArr.add(tempObj);
180
}else if(tempObj instanceof String){
181
tempArr.add(charFilter((String) tempObj));
182
}else {
183
System.out.println("未知的数据类型:"+tempObj.toString());
184
}
185
}
186
jsonObject.put(key,tempArr);
187
}
188
}
189
// return tempObj;
190
}
191
192
// getParameter开头的方法,过滤的是在parameter中存在的数据
193
public Map getParameterMap() {
194
return params;
195
}
196
197
public Enumeration getParameterNames() {
198
@SuppressWarnings("unchecked")
199
Vector l = new Vector(params.keySet());
200
return l.elements();
201
}
202
203
/**
204
* 覆盖getHeader方法,将参数名和参数值都做xss过滤。<br/>
205
* 如果需要获得原始的值,则通过super.getHeaders(name)来获取<br/>
206
* getHeaderNames 也可能需要覆盖
207
*/
208
// @Override
209
// public String getHeader(String name) {
210
// String value = super.getHeader(charFilter(name));
211
// if (value != null) {
212
// value = charFilter(value);
213
// }
214
// return value;
215
// }
216
217
public String[] getParameterValues(String name) {
218
Object v = params.get(name);
219
if (v == null) {
220
return null;
221
} else if (v instanceof String[]) {
222
String[] value = (String[]) v;
223
for (int i = 0; i < value.length; i++) {
224
value[i] = this.charFilter(value[i]);
225
}
226
return value;
227
} else if (v instanceof String) {
228
String value = (String) v;
229
value = this.charFilter(value);
230
return new String[] { value };
231
} else {
232
return new String[] { v.toString() };
233
}
234
}
235
236
public String getParameter(String name) {
237
Object v = params.get(name);
238
if (v == null) {
239
return null;
240
} else if (v instanceof String[]) {
241
String[] strArr = (String[]) v;
242
if (strArr.length > 0) {
243
String value = strArr[0];
244
value = this.charFilter(value);
245
return value;
246
} else {
247
return null;
248
}
249
} else if (v instanceof String) {
250
String value = (String) v;
251
value = this.charFilter(value);
252
return value;
253
} else {
254
return v.toString();
255
}
256
}
257
private static boolean isGoodJson(String json) {
258
if (StringUtils.isBlank(json)) {
259
return false;
260
}
261
try {
262
new JsonParser().parse(json);
263
return true;
264
} catch (JsonParseException e) {
265
return false;
266
}
267
}
268
/**
269
* 字符串遍历过滤
270
*
271
* @param value
272
* @return
273
*/
274
private String charFilter(String value) {
275
// 过滤script等 转成空
276
for (String str : illegalArr) {
277
value = value.replaceAll("(?i)" + str, ""); // (?i)忽略大小写
278
}
279
// 过滤<等
280
for (Entry<String, String> entry : illegalMap.entrySet()) {
281
value = value.replaceAll(entry.getKey(), entry.getValue());// 转义非法字符
282
}
283
284
// 过滤\r\n,解决HTTP响应拆分漏洞
285
value = value.replaceAll("\r\n", "");
286
return value;
287
}
288
289
public static Map<String, String> getParamMap(HttpServletRequest request) {
290
return getParamMap(request.getParameterMap());
291
}
292
293
public static Map<String, String> getParamMap(Map<String, String[]> requestMap) {
294
Map<String, String> paramMap = new HashMap<String, String>();
295
for (Entry<String, String[]> entry: requestMap.entrySet()) {
296
if (entry.getValue().length == 1) {
297
paramMap.put(entry.getKey(), entry.getValue()[0]);
298
} else {
299
String[] values = entry.getValue();
300
String value = "";
301
for (int i = 0; i < values.length; i++) {
302
value += values[i] + ",";
303
}
304
value = value.substring(0, value.length() - 1);
305
paramMap.put(entry.getKey(), value);
306
}
307
}
308
return paramMap;
309
}
310
311
/**
312
* 将实体直接设置在RequestAttribute中,前端使用${属性名}来获取
313
*
314
* @author Lihhz
315
* @param request
316
* @param entity
317
*/
318
public static <T> void saveToRequestAttribute(HttpServletRequest request, T entity) {
319
try {
320
if (entity == null)
321
return;
322
if (entity instanceof Map) {
323
@SuppressWarnings("rawtypes")
324
Map map = (Map) entity;
325
for (Object key : map.keySet())
326
request.setAttribute(key.toString(), map.get(key));
327
return;
328
}
329
Method[] MethodArr = entity.getClass().getDeclaredMethods();
330
StringBuffer sbStr = new StringBuffer(50);
331
for (Method method : MethodArr)
332
if (method.getModifiers() == 1) {
333
sbStr.append(method.getName());
334
if (sbStr.indexOf("get") == 0) {
335
sbStr.delete(0, 3).setCharAt(0, (char) (sbStr.charAt(0) + ' '));
336
Object value = method.invoke(entity, new Object[0]);
337
request.setAttribute(sbStr.toString(), value);
338
}
339
sbStr.delete(0, sbStr.length());
340
}
341
} catch (Exception e) {
342
e.printStackTrace();
343
}
344
}
345
}
3.总结
a 目前我知道的后端获取数据方式有:1,request的getParameter及类似系列数据;2,request的getInputStream方法,这个主要是读取数据流的
b spring在controller中的参数注入使用的应该是request的getInputStream
c request的数据流及参数一经读取就不再存在,所以在后续的controller中是无法获取的。为了避免这个问题,就需要继承HttpServletRequestWrapper,并重写其中的getParameter系列和getInputStream、getReader