springboot中使用Filter

1.过滤器Bean注册:

@SpringBootApplication //等同于 @Configuration @EnableAutoConfiguration @ComponentScan
public class SpringbootFilterDemoApp {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootFilterDemoApp.class, args);
    }

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new AuthorizationFilter()); // 自己的filter

        List<String> urlPatterns = new ArrayList<>();
        urlPatterns.add("/openapi/*");
        registrationBean.setUrlPatterns(urlPatterns);
        return registrationBean;
    }
}

2.编写自定义过滤器

以下是自己的filter类,继承Filter接口。
对于满足条件的请求,使用filterChain.doFilter(request, response);
将连接转发到目的地,不满足,则直接通过response写入错误信息。

/**
 * 过滤器:校验接口访问权限
 */
public class AuthorizationFilter implements Filter{

    private static final Logger logger = LoggerFactory.getLogger(AuthorizationFilter.class);

    private CheckAuth checkAuth;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 将请求转换成HttpServletRequest 请求
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse rsp = (HttpServletResponse) servletResponse;
        // 取得接口URI
        String currentURI = req.getRequestURI();
        // 注入checkAuth对象
        。。。
        // 读取请求参数
        。。。

        if (requestWrapper == null) {
            strError = "请求方式错误!";
        } else {
            if ("".equals(accessToken)) {
                strError = "缺少必要的参数";
            } else {
                // 校验接口权限
                if (checkAuth.checkAuth(accessToken, currentURI)) {
                    // Filter 只是链式处理,请求依然转发到目的地址。
                    filterChain.doFilter(requestWrapper, rsp);
                    return;
                } else {
                    strError = "权限不足";
                }
            }
        }

        rsp.setCharacterEncoding("UTF-8");
        rsp.setContentType("application/json; charset=utf-8");
        String rspValue = "";   // 返回错误json信息
        logger.info("返回:{}", rspValue);
        rsp.getWriter().write(rspValue);
    }

    @Override
    public void destroy() {

    }
}

注意事项
1.filter中注入对象
filter的加载在servlet之前。所以在Filter中使用@Autowired注入对象CheckAuth肯定会失败。我们可以使用WebApplicationContextUtils来获取对象。(可参考:web.xml 中的listener、 filter、servlet 加载顺序及其详解)

// 注入checkAuth对象
ServletContext sc = req.getSession().getServletContext();
WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(sc);
if (context != null && context.getBean("checkAuth") != null && checkAuth == null) {
    checkAuth = context.getBean(CheckAuth.class);
}

2.流的读取
读取请求参数:对于post请求,我们通过stream流进行读取,但是会发现,直接读取response流中的数据后,使用filterChain.doFilter(requestWrapper, rsp);请求,会报错:没有请求内容。
  因为:
  stream流的意思就是说当你读取之后就无法回到上一次读取的数据。所以说流是单向的。当第一个filter中读取流之后流已经被读完。所以无法继续读取。所以第二个filter中读不到数据。
  为了防止流读取一次后就没有了, 所以需要将流继续写出去。
  下面是对Request的封装。

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;  
import java.io.IOException;  
import java.io.InputStreamReader;  
import java.nio.charset.Charset;  
import java.util.Enumeration;  

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;

/**
 * httpServletRequst封装类
 */
public class HttpServletRequestWrapper extends
        javax.servlet.http.HttpServletRequestWrapper {

    private final byte[] body;  

    public HttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8"));  
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {

        final ByteArrayInputStream bais = new ByteArrayInputStream(body);

        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

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

            @Override
            public void setReadListener(ReadListener listener) {

            }

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

    @Override
    public String getHeader(String name) {
        return super.getHeader(name);
    }

    @Override
    public Enumeration<String> getHeaderNames() {
        return super.getHeaderNames();
    }

    @Override
    public Enumeration<String> getHeaders(String name) {
        return super.getHeaders(name);
    }
}  

request读取数据工具类

import java.io.BufferedReader;
import java.io.IOException;  
import java.io.InputStream;  
import java.io.InputStreamReader;  
import java.nio.charset.Charset;  

import javax.servlet.ServletRequest;  

public class HttpHelper {  
    /**
     * 获取请求Body
     *
     * @param request
     * @return
     */  
    public static String getBodyString(ServletRequest request) {  
        StringBuilder sb = new StringBuilder();  
        InputStream inputStream = null;  
        BufferedReader reader = null;  
        try {  
            inputStream = request.getInputStream();  
            reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));  
            String line;
            while ((line = reader.readLine()) != null) {  
                sb.append(line);  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            if (inputStream != null) {  
                try {  
                    inputStream.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
            if (reader != null) {  
                try {  
                    reader.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
        return sb.toString();  
    }  
}  

3.获取请求参数
get、post获取请求参数的方式是不一样的。

if (req.getMethod().equals("POST")) {
    requestWrapper = new HttpServletRequestWrapper(req);
    String reqParamsStr = HttpHelper.getBodyString(requestWrapper);
    if(reqParamsStr.length() >0) {
        // 从json字符串获取参数
        accessToken = "";
    }
} else if (req.getMethod().equals("GET")) {
    requestWrapper = req;
    String[] tokens = req.getParameterValues("accessToken");
    if (tokens != null && tokens.length > 0) {
        accessToken = tokens[0];
    }
}

原文链接:https://blog.csdn.net/u014207158/article/details/82864764

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值