针对全局的接口出入参加解密-AES/ECB/PKCS5Padding

首先 -  AES加密的工具类,将密钥通过枚举类进行保存。

package com.ha.common.utils;

import com.ha.common.enums.EncryptEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Base64Utils;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

/**
 * @author pph
 * @date 2022/7/8 9:54
 * @desciption
 */
@Slf4j
public class AesUtils {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(AesUtils.class);

    /**
     * key 加密算法
     */
    private static final String KEY_ALGORITHM = "AES";

    /**
     * 固定值
     */
    private static final String SECRET_RANDOM = "SHA1PRNG";

    /**
     * 编码方式
     */
    public static final String ENCODING_TYPE = "UTF-8";

    /**
     * 默认的加密算法
     */
    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";

    /**
     * 私钥
     */
    private static final String ASSETS_DEV_PWD_FIELD = EncryptEnum.ENCRYPT_ENUM.getCode();

    /**
     * 加密
     */
    public static String encrypt(String content, String password) {

        try {
            // 创建密码器
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);

            byte[] byteContent = content.getBytes(ENCODING_TYPE);
            // 初始化为加密模式的密码器
            cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(password));
            // 加密
            byte[] result = cipher.doFinal(byteContent);
            // 通过Base64转码返回
            return Base64Utils.encodeToString(result);
        } catch (Exception e) {
            LOGGER.info("aesencrypt000 error ", e);
        }

        return null;
    }

    /**
     * AES 解密
     */
    public static String decrypt(String content, String password) {

        try {
            //实例化
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
            //使用密钥初始化,设置为解密模式
            cipher.init(Cipher.DECRYPT_MODE, getSecretKey(password));
            SecretKeySpec secretKey = getSecretKey(password);
            //执行操作
            byte[] result = cipher.doFinal(Base64Utils.decodeFromString(content));
//            Base64 base64 = new Base64();
//            byte[] result = base64.decodeBase64(password.getBytes());
            return new String(result, "utf-8");
        } catch (Exception e) {
            LOGGER.info("aesdecrypt000 error ", e);
        }

        return null;
    }

    /**
     * 生成加密秘钥
     */
    private static SecretKeySpec getSecretKey(String password) {

        //返回生成指定算法密钥生成器的 KeyGenerator 对象
        KeyGenerator kg;
        try {
            kg = KeyGenerator.getInstance(KEY_ALGORITHM);
            SecureRandom secureRandom = SecureRandom.getInstance(SECRET_RANDOM);
            secureRandom.setSeed(password.getBytes());
            //AES 要求密钥长度为 128
            kg.init(128, secureRandom);
            //生成一个密钥
            SecretKey secretKey = kg.generateKey();
            // 转换为AES专用密钥
            return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            LOGGER.info("aesgetSecretKey000 error ", e);
        }

        return null;
    }



    public static void main(String[] args) {

        String str="MK9wOrPiGGT1eCc5ovV9ggZPBD7HjsrW6HOOnD0mMd5sTF/IupPGJBelRKgpPPZGxdbap2VGqLu44OU4tv0EmnRUdP8mkLyO7Rodw88qEFav8jyP8TnVxpRrjWOZCo+6";
        System.out.println(AesUtils.decrypt(str, EncryptEnum.ENCRYPT_ENUM.getCode()));

        System.out.println("---------------------------");
        String str1="BwZiUICxJIZ4Ua7VrdZTVEubw/UCNB/sxcS6iqswaT3lU942bfjbZyIdlO3IWkEWhxoG9vqBwZjL+ysL83gtiK+ZHEf/wJl8orRi0Ty3IsWmC7voZch2bOsVzQRQqGSHCq99iiBysmeGZh5PxrIspYy+O6AN/nTvi9t3Mj3JfK9vKcv+fq6ypqt5XyUaXQkcOR4rUELM9YtU78c9zkS994Z0EgwInGZJXKZxsb3qEiu6jAu2FUWYs8OtjM3XjfaZV3bVuvTNMbjJIRSkbvpi8m2hvmLjBYBj163ptqPuNxYX9Kyw2aK4nHO9ictlz0BDWjtVaKi0923HVKUvDFN5JtPXd1FPrg7N7+L56+jKsPfBVX4wjmCrj1RK/oZEjUDNwzXfAnYQA9dMSur8Clkcc0fN0qjBScu7DUBkWainnhC0U0jHCp04/lPMTlXgmhaOnXEakozP3g8M0KvO3CSRwWUGU119ZIEbUPZtaSv6SiNbLDn7jLM4n1cS3XgS663J1zr8CmC7cBeaJL6GnpLaEvqhaafwidTcdueM5KABji/VhX4N9EfZd0G7T2qMkitmDLNCw9BMsIi1tBnbsZU2+rln7baowVZnRyG6SDGHDiFKDlyvWU4MUJPqxI6xm8rnsPYTdIW5KOo//1OQqqMTy/yRz33IJQa8tWBGbGEr2Hs91ItH4DlLlowI0RIAHhYwpqN1EsYhU+lkyeba7uuz8hdkPXenJnW70xuYT2sFqYWVBeFCXV0aqxzpvqVAiGiJdEo5gnKUNVCaKlsXbOEKjfSpLYzMUwcRw8b9V8VdsPlkxBc3talx86eJvdOlGo0HrTuKfxv6nS0rSR9xH50VTPx2IvcPTEYMe9398nkdbQoH5gA7pfOHB39m6W6WLS1SGLhA8A8ucvh+iRvmiSGWW6lTptsQW0AVlGbQaqZMF5sBHZV0Of6HUB9JFZylJTE71oD4J9JZZdphmKozJuLtWtYiNb/H80TBDUoph1n3HTU=";
        System.out.println(AesUtils.decrypt(str1, EncryptEnum.ENCRYPT_ENUM.getCode()));
    }

}

 枚举类 - 设置密钥

package com.ha.common.enums;

/**
 * @author pph
 * 加解密密钥枚举
 */
public enum EncryptEnum
{
    ENCRYPT_ENUM("666666abcdefg");

    private final String code;

    EncryptEnum(String code)
    {
        this.code = code;
    }

    public String getCode()
    {
        return code;
    }

}

本文的方法是通过过滤器进行接口出入参的加解密,这是过滤器的代码部分

2、新建过滤器

这个过滤器没有指定了url进入规则,暂时所有的url都能进入到此过滤器中。在doFilter方法中使用了自定义的ResponseWrapper对response进行封装。Controller接口走完之后获取到接口返回的数据并再次封装到response。

package com.ha.common.filter;

import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSONObject;
import com.ha.common.enums.EncryptEnum;
import com.ha.common.utils.AesUtils;

/**
 * Repeatable 过滤器
 */
public class RepeatableFilter implements Filter
{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException
    {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException
    {
//        chain.doFilter(request, response);
        if(((HttpServletRequest) request).getMethod().equals("GET") || ((HttpServletRequest) request).getMethod().equals("POST")||
           ((HttpServletRequest) request).getMethod().equals("PUT") || ((HttpServletRequest) request).getMethod().equals("DELETE"))
        {
            String requestURI = ((HttpServletRequest) request).getRequestURI();
            //用户登录是否加密解密
//            if (requestURI.equals("/busi/user/app/loginByPwd")){
//                chain.doFilter(request, response);
//                return;
//            }
            //上传文件不许加解密
            if (requestURI.equals("/system/user/profile/avatar")){
                chain.doFilter(request, response);
                return;
            }

        AesRequestWrapper aesrequestWrapper = null;
        AesResponseWrapper aesResponseWrapper = null;

        aesrequestWrapper = new AesRequestWrapper((HttpServletRequest) request);
        aesResponseWrapper = new AesResponseWrapper((HttpServletResponse) response);
        chain.doFilter(aesrequestWrapper, (ServletResponse) aesResponseWrapper);
        // 获取response返回的内容并重新写入response, 若获取到的数据是乱码,可设置response的编码为系统默认编码集
        String result = aesResponseWrapper.getResponseData(response.getCharacterEncoding());

        //加密
        String encryptResponse = AesUtils.encrypt(result, EncryptEnum.ENCRYPT_ENUM.getCode());

        Object object = JSONObject.parse(result);
        response.getOutputStream().write(encryptResponse.getBytes());
        response.getOutputStream().flush();
        response.getOutputStream().close();
        }
    }
    
    @Override
    public void destroy()
    {

    }

    /**
     * 路径不处理
     * @param request
     * @param strArr
     * @return
     */
    public boolean isIgnore(HttpServletRequest request,String[] strArr) {
        String path=request.getRequestURI();
        for(String ignore:strArr) {
            if(path.contains(ignore)) {
                return true;
            }
        }
        return false;
    }

}

之后就是关于对request请求中body的修改及response的加密。博主这边封装了两个类去解决的。

AesResponseWrapper获取接口的返回值并执行加密
package com.ha.common.filter;

import com.alibaba.fastjson.JSONObject;

import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;

public class AesResponseWrapper extends HttpServletResponseWrapper {

    private ByteArrayOutputStream buffer = null;

    private ServletOutputStream out = null;

    private PrintWriter writer = null;

    public AesResponseWrapper(HttpServletResponse response) throws IOException {
        super(response);
        buffer = new ByteArrayOutputStream();
        out = new WapperedOutputStream(buffer);
        writer = new PrintWriter(new OutputStreamWriter(buffer, this.getCharacterEncoding()));
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        return out;
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        return writer;
    }

    @Override
    public void flushBuffer() throws IOException {
        if (out != null) {
            out.flush();
        }
        if (writer != null) {
            writer.flush();
        }
    }

    @Override
    public void reset() {
        buffer.reset();
    }

    /**
     * @Description: 获取response中数据的方法
     **/
    public String getResponseData(String charset) throws IOException {
        flushBuffer();//将out、writer中的数据强制输出到WapperedResponse的buffer里面,否则取不到数据
        System.out.println(buffer.toString());
        byte[] bytes = buffer.toByteArray();
        System.out.println(buffer);
        JSONObject parse = (JSONObject) JSONObject.parse(buffer.toString());
        System.out.println(parse);
        //            return new String(bytes, "UTF-8");
        return String.valueOf(buffer);

    }

    //内部类,对ServletOutputStream进行包装,指定输出流的输出端
    private class WapperedOutputStream extends ServletOutputStream {

        private ByteArrayOutputStream bos = null;

        public WapperedOutputStream(ByteArrayOutputStream stream) throws IOException {
            bos = stream;
        }

        //将指定字节写入输出流bos
        @Override
        public void write(int b) throws IOException {
            bos.write(b);
        }

        @Override
        public boolean isReady() {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public void setWriteListener(WriteListener listener) {
            // TODO Auto-generated method stub

        }
    }

}

AesRequestWrapper获取请求的Body并修改重新带到接口
package com.ha.common.filter;

import com.alibaba.fastjson.JSONObject;
import com.ha.common.enums.EncryptEnum;
import com.ha.common.utils.AesUtils;
import com.ha.common.utils.StringUtils;
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 java.io.*;

/**
 * @author pph
 */
public class AesRequestWrapper extends HttpServletRequestWrapper {

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

    /**
     * 存储请求数据
     */
    private String body;

    public AesRequestWrapper(HttpServletRequest request) {
        super(request);
        renewBody(request);
    }

    /**
     * 重写getInputStream方法
     */
    @Override
    public ServletInputStream getInputStream() {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

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

            @Override
            public void setReadListener(ReadListener readListener) {
            }

            @Override
            public int read() {
                return byteArrayInputStream.read();
            }
        };
    }

    /**
     * 重写getReader方法
     */
    @Override
    public BufferedReader getReader() {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }

    /**
     * 读取body的值
     */
    private void renewBody(HttpServletRequest request) {
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        try {
            InputStream inputStream = request.getInputStream();
            if (inputStream != null) {
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                char[] charBuffer = new char[128];
                int bytesRead = -1;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
                if(!StringUtils.isEmpty(stringBuilder)){
                    String str = stringBuilder.toString();
                    JSONObject parse = (JSONObject) JSONObject.parse(str);
                    String data = parse.getString("data");
                    //data加密代码为空  不解密
                    if (StringUtils.isEmpty(parse.getString("data"))){
                        body = str;
                        return;
                    }
                    body = AesUtils.decrypt(data, EncryptEnum.ENCRYPT_ENUM.getCode());
                    System.out.println(body);
                }
            }
        } catch (Exception ex) {
            logger.error("报错请求接口的路径:{}",request.getRequestURI());
            logger.error("请求入参aes解密失败:{}",ex);
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException ex) {
                    logger.error("请求入参base64转换失败:{}",ex);
                }
            }
        }
    }

    public String getBody() {
        return body;
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值