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
    }

}

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

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



原文地址:https://www.cnblogs.com/kaile/p/10195388.html

时间: 2025-01-30 05:53:49

Springboot 使用过滤器进行加密解密(二)的相关文章

Java加密解密(二) Base64编码

1. Base64的由来 Base64最早用于解决电子邮件传输问题.由于"历史问题",早期的电子邮件网关只允许传输ASCII(二进制为00000000-01111111)字符,如果有非ASCII字符经过这种网关时, 字符的二进制位可能会被篡改(如将10000001改为00000001).由此产生了Base64编码来保证非ASCII字符的传输. 2. 原理 Base64顾名思义是一种基于64个字符的编码算法.如下是Base64的字符映射表,详情参见RFC 2045 Value Encod

二维码加密解密工具——优密(手机版)正式上线!

Lizcst Software Lab第一款Android平台应用软件--优密正式发布! 下面是软件的简介及功能特色: 优密--二维码加解密工具该工具是一款强大的二维码加密与解密扫码的手机软件,适用于Android 2.2及以上平台.使用本工具可以制作出具有加密信息的二维码,该二维码无法被普通的二维码扫码工具解码其中的内容,可以非常方便的将机密的信息隐藏在二维码中,帮助保护机密信息不被非法的扫码解读! 优密二维码加密解密工具主要特点: 1.制作包含加密信息的二维码:软件可在手机中直接生成需要的内

二维码加密解密工具——优密 更新版本发布!

优密--二维码加解密工具该工具是一款强大的二维码加密与解密扫码的手机软件,适用于Android 2.2及以上平台.使用本工具可以制作出具有加密信息的二维码,该二维码无法被普通的二维码扫码工具解码其中的内容,可以非常方便的将机密的信息隐藏在二维码中,帮助保护机密信息不被非法的扫码解读! 优密二维码加密解密工具主要特点: 1.制作包含加密信息的二维码:软件可在手机中直接生成需要的内容的加密二维码,无需借助电脑等设备,该二维码外观与普通二维码无异,并且也可被常见的普通二维码扫码工具扫描识别,但是却无法

使用X.509数字证书加密解密实务(二)-- 使用RSA证书加密敏感数据

一.  使用RSA证书加.解密敏感数据 X.509证书标准支持三种不对称加密算法:RSA, DSA, Diffie-Hellman algorithms.最常用的是RSA算法.所以本文就以前面章节使用makecert工具生成的生成的MyTestCert证书进行加密解密,这个证书具有RSA算法1024位的密钥对. Figure 12. RSA加密解密过程 1. 生成证书.分发证书 证书使用前面“使用makecert工具获得”章节生成的MyTestCert,当然也可以是从商业CA获得的证书. 你获得

Openssl及加密解密(二)openssl

openssl是一个条件实现了上百种算法.实现了单向加密工具等一组套件,代码量很小但是功能强大.它有三部分组成: libcrypto:通用功能的加密库,软件开发时可以直接调用 libssl:实现TLS/SSL的功能 openssl:多功能命令行工具,加密.解密.创建CA.证书.一对秘钥等 openssl enc加密解密命令: 参数 说明 -des3 是指定加密算法 -a 是输出文件按base64内容输出,否则就是二进制的 -in 要加密的文件 -out 加密后的文件 -salt 加盐 -d 表示

SpringBoot中幸运飞艇网站制作接口加密解密统一处理

在和客户端中的接口交互时,要取得更高的安全性,幸运飞艇网站制作q<217.17.9.34.0.8>或许我们需要对其进行加密(请求参数加密和服务端解密).信息返回加密(服务端加密和客户端解密),然后不是所有接口都如此,有些接口可能不用,可以通过注解来简单达到此要求. 将接口参数的加密解密和返回信息的加密解密分开,分别定义注解,利用Controller的ControllerAdvice来拦截所有的请求,在其中判断是否需要加密解密,即可达到要求.使用方法:使用 DecryptRequest 和 En

加密解密

在现代密码学中,加密方法大致可分为对称密钥加密(对称加密)和公开密钥加密(非对称加密). 一. 对称加密(Symmetric-key algorithm,或对等加密: Reciprocal cipher ) 对称加密,即加密和解密使用同一个密钥,或者知道一方密钥能够轻易计算出另一方密钥.其解密(decryption)算法等同于加密算法,也就是说,要还原对等加密的密文,套用加密同样的算法即可得到明文. 对称加密的速度比非对称加密快很多,在很多场合都需要对称加密. 对称加密又可分为分组密码(分组加密

C#加密解密(DES,AES,Base64,md5,SHA256,RSA,RC4)

一:异或^简单加解密(数字类型) 1:原理: 异或用于比较两个二进制数的相应位,在执行按位"异或"运算时,如果两个二进制数的相应位都为1或者都为0,则返回0;如果两个二进制数的相应位其中一个为1另一个为0,则返回1. //对数字加密 int P_int_Num, P_int_Key;//定义两个值类型变量 string Encryptstr = (P_int_Num ^ P_int_Key).ToString();//加密数值 //对数字解密 int P_int_Key, P_int_

python RSA加密解密及模拟登录cnblog

1.公开密钥加密 又称非对称加密,需要一对密钥,一个是私人密钥,另一个则是公开密钥.公钥加密的只能私钥解密,用于加密客户上传数据.私钥加密的数据,公钥可以解密,主要用于数字签名.详细介绍可参见维基百科. 2.RSA加密算法 RSA加密属于非对称加密.RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥.维基百科中对RSA算法的安全性进行说明:RSA加密算法 "对极大整数做因式分解的难度决定了RSA算法的可靠性.换言