Spring Boot 学习笔记(八) 整合 Filter

202 阅读6分钟

Spring Boot 学习笔记(八) 整合 Filter


Spring Boot 学习笔记(八) 整合 Filter

1. 创建自定义的 Filter

创建一个 DemoFilter

1package com.zdran.springboot.filter;
2
3import org.slf4j.Logger;
4import org.slf4j.LoggerFactory;
5
6import javax.servlet.*;
7import java.io.IOException;
8
9/**
10 * Create by ranzd on 2018/8/9
11 *
12 * @author cm.zdran@gmail.com
13 */
14public class DemoFilter implements Filter{
15    private Logger logger = LoggerFactory.getLogger(DemoFilter.class);
16    @Override
17    public void init(FilterConfig filterConfig) throws ServletException {
18        logger.info("初始化 DemoFilter ");
19    }
20
21    @Override
22    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
23            throws IOException, ServletException {
24        logger.info("拦截到参数:{}", servletRequest.getParameterMap());
25        if (true) {
26            filterChain.doFilter(servletRequest,servletResponse);
27        }
28        logger.info("拦截到参数。请求被拦截");
29    }
30
31    @Override
32    public void destroy() {
33        logger.info("销毁 DemoFilter ");
34    }
35}
36

核心的方法是 doFilter,可以在这个方法内对参数进行校验,通过servletRequest可以获取到请求中的参数。根据参数进行拦截。

1filterChain.doFilter(servletRequest,servletResponse);

如果调用了这行代码说明不拦截这次请求,如果没有调用这行代码,这次请求请求将被拦截。

2. 初始化 Filter

将这个Filter注入到容器中,创建 FilterConfig 类

1@Configuration
2public class FilterConfig {
3    private Logger logger = LoggerFactory.getLogger(FilterConfig.class);
4    @Bean
5    public FilterRegistrationBean xssFilterRegistrationBean() {
6        logger.info("初始化 DemoFilter 过滤器 Bean");
7        FilterRegistrationBean<Filter> initXssFilterBean = new FilterRegistrationBean<>();
8        initXssFilterBean.setFilter(new DemoFilter());
9        initXssFilterBean.setOrder(1);
10        initXssFilterBean.setEnabled(true);
11        initXssFilterBean.addUrlPatterns("/*");
12        initXssFilterBean.setDispatcherTypes(DispatcherType.REQUEST);
13        return initXssFilterBean;
14    }
15}

setOrder方法可以对这个 Filter 设置一个优先级,这个值越小,越先被执行。尽量不要与其他的 Filter 冲突

3. HttpServletRequestWrapper 修改参数

有些时候我们可能需要对参数进行修改,比如XSS过滤,防SQL注入等。这个时候我们可以通过HttpServletRequestWrapper 来对参数进行修改。 创建 DemoHttpServletRequestWrapper。通过重写这个类的一些方法来对参数进行修改。

1package com.zdran.springboot.filter;
2
3import org.slf4j.Logger;
4import org.slf4j.LoggerFactory;
5
6import javax.servlet.ReadListener;
7import javax.servlet.ServletInputStream;
8import javax.servlet.http.HttpServletRequest;
9import javax.servlet.http.HttpServletRequestWrapper;
10import javax.servlet.http.HttpSession;
11import java.io.*;
12import java.util.Map;
13
14/**
15 * Create by ranzd on 2018/8/9
16 *
17 * @author cm.zdran@gmail.com
18 */
19public class DemoHttpServletRequestWrapper extends HttpServletRequestWrapper {
20
21    private Logger logger = LoggerFactory.getLogger(DemoHttpServletRequestWrapper.class);
22
23    public DemoHttpServletRequestWrapper(HttpServletRequest request) {
24        super(request);
25    }
26
27    @Override
28    public String getHeader(String name) {
29        String value = super.getHeader(name);
30        logger.info("获取 Header 中的参数:{}", value);
31        return value;
32    }
33
34    @Override
35    public String getParameter(String name) {
36        String value = super.getParameter(name);
37        logger.info("获取 getParameter 中的参数:{}", value);
38        return value;
39    }
40
41    @Override
42    public Map<String, String[]> getParameterMap() {
43        Map<String, String[]> map = super.getParameterMap();
44        logger.info("获取 getParameterMap 中的参数:{}", map);
45        return map;
46    }
47
48    @Override
49    public HttpSession getSession() {
50        HttpSession session = super.getSession();
51        logger.info("获取 getCookies 中的cookie:{}", session);
52        return session;
53    }
54
55    @Override
56    public Object getAttribute(String name) {
57        Object obj = super.getAttribute(name);
58        logger.info("获取 getCookies 中的cookie:{}", obj);
59
60        return obj;
61    }
62
63    @Override
64    public String[] getParameterValues(String name) {
65        String[] value = super.getParameterValues(name);
66        logger.info("获取 getParameter 中的参数:{}", value);
67        return value;
68    }
69
70    @Override
71    public ServletInputStream getInputStream() throws IOException {
72        BufferedReader br = new BufferedReader(new InputStreamReader(super.getInputStream()));
73        StringBuilder resultBuilder = new StringBuilder();
74        String line;
75        while ((line = br.readLine()) != null) {
76            resultBuilder.append(line);
77        }
78        String result = resultBuilder.79    [native code]
80}">toString();
81        logger.info("获取 getInputStream 中的参数:{}", result);
82        return new WrappedServletInputStream(new ByteArrayInputStream(result.getBytes()));
83    }
84
85    /**
86     * 读取 RequestBody 中的参数时需要重新再次写入到流中,
87     * 否则在 Controller 中会读取不到参数。
88     */
89    private class WrappedServletInputStream extends ServletInputStream {
90        public void setStream(InputStream stream) {
91            this.stream = stream;
92        }
93
94        private InputStream stream;
95
96        public WrappedServletInputStream(InputStream stream) {
97            this.stream = stream;
98        }
99
100        @Override
101        public int read() throws IOException {
102            return stream.read();
103        }
104
105        @Override
106        public boolean isFinished() {
107            return true;
108        }
109
110        @Override
111        public boolean isReady() {
112            return true;
113        }
114
115        @Override
116        public void setReadListener(ReadListener readListener) {
117
118        }
119    }
120}
121

注意: 在读取 RequestBody中的参数的时候需要用 getInputStream 方法,而且读取结束后,必须再次向该流中写入,否则Controller将读取不到参数。

转载请注明出处
本文链接:zdran.com/20180809.ht…