U2647's blog 一个热爱学习的 Java 程序员,喜欢 Vue,喜欢深度学习 Dubbo Flutter SpringBoot Debug Notes Java LeetCode Python Redis Android DesignPattern mdi-home-outline 首页 mdi-cloud-outline 标签云 mdi-timeline-text-outline 时间轴 mdi-draw-pen 文章总数 62
Spring Boot 学习笔记(八) 整合 Filter Spring Boot 学习笔记(八) 整合 Filter Spring Boot Filter Git HttpServletRequestWrapper mdi-cursor-default-click-outline 点击量 62

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

1. 创建自定义的 Filter

创建一个 DemoFilter

package com.zdran.springboot.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import java.io.IOException;

/**
 * Create by ranzd on 2018/8/9
 *
 * @author cm.zdran@gmail.com
 */
public class DemoFilter implements Filter{
    private Logger logger = LoggerFactory.getLogger(DemoFilter.class);
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        logger.info("初始化 DemoFilter ");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        logger.info("拦截到参数:{}", servletRequest.getParameterMap());
        if (true) {
            filterChain.doFilter(servletRequest,servletResponse);
        }
        logger.info("拦截到参数。请求被拦截");
    }

    @Override
    public void destroy() {
        logger.info("销毁 DemoFilter ");
    }
}

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

filterChain.doFilter(servletRequest,servletResponse);

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

2. 初始化 Filter

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

@Configuration
public class FilterConfig {
    private Logger logger = LoggerFactory.getLogger(FilterConfig.class);
    @Bean
    public FilterRegistrationBean xssFilterRegistrationBean() {
        logger.info("初始化 DemoFilter 过滤器 Bean");
        FilterRegistrationBean<Filter> initXssFilterBean = new FilterRegistrationBean<>();
        initXssFilterBean.setFilter(new DemoFilter());
        initXssFilterBean.setOrder(1);
        initXssFilterBean.setEnabled(true);
        initXssFilterBean.addUrlPatterns("/*");
        initXssFilterBean.setDispatcherTypes(DispatcherType.REQUEST);
        return initXssFilterBean;
    }
}

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

3. HttpServletRequestWrapper 修改参数

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

package com.zdran.springboot.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.util.Map;

/**
 * Create by ranzd on 2018/8/9
 *
 * @author cm.zdran@gmail.com
 */
public class DemoHttpServletRequestWrapper extends HttpServletRequestWrapper {

    private Logger logger = LoggerFactory.getLogger(DemoHttpServletRequestWrapper.class);

    public DemoHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    @Override
    public String getHeader(String name) {
        String value = super.getHeader(name);
        logger.info("获取 Header 中的参数:{}", value);
        return value;
    }

    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        logger.info("获取 getParameter 中的参数:{}", value);
        return value;
    }

    @Override
    public Map<String, String[]> getParameterMap() {
        Map<String, String[]> map = super.getParameterMap();
        logger.info("获取 getParameterMap 中的参数:{}", map);
        return map;
    }

    @Override
    public HttpSession getSession() {
        HttpSession session = super.getSession();
        logger.info("获取 getCookies 中的cookie:{}", session);
        return session;
    }

    @Override
    public Object getAttribute(String name) {
        Object obj = super.getAttribute(name);
        logger.info("获取 getCookies 中的cookie:{}", obj);

        return obj;
    }

    @Override
    public String[] getParameterValues(String name) {
        String[] value = super.getParameterValues(name);
        logger.info("获取 getParameter 中的参数:{}", value);
        return value;
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(super.getInputStream()));
        StringBuilder resultBuilder = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            resultBuilder.append(line);
        }
        String result = resultBuilder.toString();
        logger.info("获取 getInputStream 中的参数:{}", result);
        return new WrappedServletInputStream(new ByteArrayInputStream(result.getBytes()));
    }

    /**
     * 读取 RequestBody 中的参数时需要重新再次写入到流中,
     * 否则在 Controller 中会读取不到参数。
     */
    private class WrappedServletInputStream extends ServletInputStream {
        public void setStream(InputStream stream) {
            this.stream = stream;
        }

        private InputStream stream;

        public WrappedServletInputStream(InputStream stream) {
            this.stream = stream;
        }

        @Override
        public int read() throws IOException {
            return stream.read();
        }

        @Override
        public boolean isFinished() {
            return true;
        }

        @Override
        public boolean isReady() {
            return true;
        }

        @Override
        public void setReadListener(ReadListener readListener) {

        }
    }
}

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

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
我的GitHub 我的LeetCode 我的掘金
Powered by Hexo Powered by three-cards
Copyright © 2017 - {{ new Date().getFullYear() }} 某ICP备xxxxxxxx号