• 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
        }
    
    }

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

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

    
    
  • 相关阅读:
    Android的selector,背景选择器
    JAVA静态和非静态内部类
    Android应用资源--之属性(Attribute)资源
    contentprovider的学习实例总结
    转:Android 2.3 代码混淆proguard技术介绍
    忘掉旋转,利用2-3-4树,学习红黑树
    ios 定位获取当前位置信息
    地图相关
    mac下,svn配置
    NimBus一个好的开发框架
  • 原文地址:https://www.cnblogs.com/kaile/p/10195388.html
Copyright © 2020-2023  润新知