zoukankan      html  css  js  c++  java
  • Springboot 使用过滤器进行加密解密(二)

    之前写过一篇关于过滤器实现加密解密功能的文章,但是在实际开发业务中发现,还是有一些问题的,在此特地说明。

    第一:过滤器走两遍的问题:

    1.过滤器上,添加了两个注解

    第一个:@Compent   将此Filter交给Spring容器管理

    第二个:@WebFilter通过WebFilter进行Filter声明,这样容器在进行部署的时候就会处理该Filter

    2.启动类上添加的注解

    @ServletComponentScan  作用:Servlet、Filter、Listener 可以直接通过 @WebServlet、@WebFilter、@WebListener 注解自动注册(自动扫描带有过滤器注解的包)

    3.问题:项目启动后,一个请求执行两次

    原因:@Compent 启动时,会加载Filter.  @ServletComponentScan 也会扫描过滤器。所以会加载两次

    4.解决措施:

    去掉过滤器上的@Compent 注解之后,请求过滤一次。

    第二:响应结果跟加密结果不一致的问题

    1.之前使用的包装类,不知道为何,加密的结果和最终响应的结果不一致,并且是有规律的少。

    各位大神,如果知道为什么的话,麻烦指点一下。

     

    2.解决办法:直接换了一个包装类,代码如下:

    包装类代码:

    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.io.UnsupportedEncodingException;
    
    import javax.servlet.ServletOutputStream;
    import javax.servlet.WriteListener;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpServletResponseWrapper;
    
    /**
     * reponse包装类,对reponse响应进行处理后,传给客户端
     * @Author: kiki
     * @Date: 2018/12/18
     */
    public class WrapperedResponse extends HttpServletResponseWrapper {
        private ByteArrayOutputStream buffer = null;
        private ServletOutputStream out = null;
        private PrintWriter writer = null;
    
        public WrapperedResponse(HttpServletResponse resp) throws IOException {
            super(resp);
            buffer = new ByteArrayOutputStream();//真正存储数据的流
            out = new WrapperedResponse.WapperedOutputStream(buffer);
            writer = new PrintWriter(new OutputStreamWriter(buffer, this.getCharacterEncoding()));
        }
    
        //重载父类获取outputstream的方法
        @Override
        public ServletOutputStream getOutputStream() throws IOException {
            return out;
        }
    
        //重载父类获取writer的方法
        @Override
        public PrintWriter getWriter() throws UnsupportedEncodingException {
            return writer;
        }
    
        //重载父类获取flushBuffer的方法
        @Override
        public void flushBuffer() throws IOException {
            if (out != null) {
                out.flush();
            }
            if (writer != null) {
                writer.flush();
            }
        }
    
        @Override
        public void reset() {
            buffer.reset();
        }
    
        public String getContent() throws IOException {
            flushBuffer();//将out、writer中的数据强制输出到WapperedResponse的buffer里面,否则取不到数据
            return new String(buffer.toByteArray());
        }
    
        //内部类,对ServletOutputStream进行包装
        private class WapperedOutputStream extends ServletOutputStream {
            private ByteArrayOutputStream bos = null;
    
            public WapperedOutputStream(ByteArrayOutputStream stream) throws IOException {
                bos = stream;
            }
    
            @Override
            public void write(int b) throws IOException {
                bos.write(b);
            }
    
            @Override
            public boolean isReady() {
                return false;
            }
    
            @Override
            public void setWriteListener(WriteListener listener) {
    
            }
        }
    }

     过滤器代码:

    /**
     * 过滤器拦截请求,实现加密解密功能
     * 
     * @Component 将此Filter交给Spring容器管理
     * @WebFilter 通过WebFilter进行Filter声明,这样容器在进行部署的时候就会处理该Filter
     *
     * @author kiki
     */
    @WebFilter(urlPatterns = "/HMService/*", filterName = "dataFilter")
    public class DataFilter implements Filter {
    
        
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            // TODO Auto-generated method stub
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
                
                //解密请求
            
                //使用包装类 对request/response进行修改和响应
                WrapperedRequest wrapRequest = new WrapperedRequest((HttpServletRequest) request, requestBodyMw);
                WrapperedResponse wrapResponse = new WrapperedResponse((HttpServletResponse) response);
                chain.doFilter(wrapRequest, wrapResponse);
                String content = wrapResponse.getContent();
                String responseBodyMw = DES3Util.encodeCBC(content);
                logger.info("【加密返回数据为】 responseBodyMw = {}", responseBodyMw);
                response.setContentLength(-1);
                    PrintWriter out = response.getWriter();
                    System.out.println(responseString.length());
                    out.write(responseBodyMw);
                    out.flush();
                    out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void destroy() {
            // TODO Auto-generated method stub
        }
    
    }

    修改之后,加密的结果和响应的结果一致。

    说明:这是个大坑呀,刚开始没有发现这个问题,返回的是加密的字符串就认为是对的,但是客户端就是解析不了。我才知道,加密的结果和最终响应的结果不一样,特此记录。

    
    
  • 相关阅读:
    h5 穿透滚动
    Safari 导航栏
    浮层滚动问题
    兼容性常规检测
    CORS
    Webpack 一些概念
    01 离散时间信号的时域表示
    03 信道容量
    01 MATLAB基本概念
    02 字斟句酌
  • 原文地址:https://www.cnblogs.com/kaile/p/10195388.html
Copyright © 2011-2022 走看看