Web过滤器总结

来源:互联网 发布:网络语言的利与弊 编辑:程序博客网 时间:2024/05/29 23:25
1.过滤器代码
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("<", "&lt;");
43
            put(">", "&gt;");
44
            put("'", "&#39;");
45
            put("\"", "&quot;");
46
            put("/", "&#47;");
47
            put("\\\\", "&#92;");
48
            put("\\)", ")");//&#41;
49
            put("\\(", "(");//&#40;
50
            put(";", "&#59;");//&#59;
51
            put("\\[", "【");//&#91;
52
            put("\\]", "】");//&#92;
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
原创粉丝点击