SpringBoot整合AES+RSA加密(含前端代码)

目录

非对称加密和对称加密

RSA和AES简介

混合加密原因:

一、RSA工具类

二、AES工具类

三、解密工具类

四、自定义注解

五、aes加密实体类

六、加密的请求参数

七、这里使用拦截器解密

八、可以修改请求参数的request

九、RSA工具类

十、前端加密需要用到的js

十一、前端拦截器对请求统一加密

十二、为什么使用拦截器不使用aop

总结

非对称加密和对称加密

非对称加密

非对称加密算法是一种密钥的保密方法。非对称加密算法需要两个密钥:公开密钥(publickey:简称公钥)和私有密钥(privatekey:简称私钥)。

公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

对称加密

加密秘钥和解密秘钥是一样,当你的密钥被别人知道后,就没有秘密可言了

AES 是对称加密算法,优点:加密速度快;缺点:如果秘钥丢失,就容易解密密文,安全性相对比较差

RSA 是非对称加密算法 , 优点:安全 ;缺点:加密速度慢


RSA和AES简介

RSA
加密机制:属于非对称加密,公钥用于对数据进行加密,私钥对数据进行解密,两者不可逆。公钥和私钥是同时生成的,且一一对应。比如:A拥有公钥,B拥有公钥和私钥。A将数据通过公钥进行加密后,发送密文给B,B可以通过私钥进行解密。
AES
加密机制:属于对称加密,就是说,A用密钥对数据进行AES加密后,B用同样的密钥对密文进行AES解密。


加密思路

1:调用方先将请求参数用AES加密,再利用RSA公钥对AES的密钥值加密;
2:调用方将加密后的数据发送给服务端;
3:服务端接收到头信息里的加密串,先用RSA私钥解密出AES密钥值,再用解密出的AES密钥值解密请求参数;
4:处理完毕后,服务端再用AES密钥对响应参数加密;(本篇不涉及返回值加密,可以根据代码自己调试)
5:将加密后的结果返回给调用方。(本篇不涉及返回值解密,可以根据代码自己调试)

混合加密原因:

单纯的使用 RSA(非对称加密)方式,效率会很低,因为非对称加密解密方式虽然很保险,但是过程复杂,耗费时间长,性能不高;
RSA优势在于数据传输安全,且对于几个字节的数据,加密和解密时间基本可以忽略,所以用它非常适合加密 AES 秘钥(一般16个字节);
单纯的使用AES(对称加密)方式的话,非常不安全。这种方式使用的密钥是一个固定的密钥,客户端和服务端是一样的,一旦密钥被人获取,那么,我们所发的每一条数据都会被都对方破解;
AES有个很大的优点,那就是加密解密效率很高,而我们传输正文数据时,正好需要这种加解密效率高的,所以这种方式适合用于传输量大的数据内容。

一、RSA工具类

package com.ruoyi.common.utils.rsa;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;


@Slf4j
public class ActivityRSAUtil {

    /**
     * 字符集
     */
    public static String CHARSET = "UTF-8";

    /**
     * 生成密钥对
     * @param keyLength  密钥长度
     * @return KeyPair
     */
    public static KeyPair getKeyPair(int keyLength) {
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");   //默认:RSA/None/PKCS1Padding
            keyPairGenerator.initialize(keyLength);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            log.info("私钥:{}" ,getPrivateKeyString(keyPair));
            log.info("公钥:{}" ,getPublicKeyString(keyPair));
            return keyPair;
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("生成密钥对时遇到异常" +  e.getMessage());
        }
    }

    /**
     * 获取公钥
     */
    public static byte[] getPublicKey(KeyPair keyPair) {
        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
        return rsaPublicKey.getEncoded();
    }

    /**
     * 获取私钥
     */
    public static byte[] getPrivateKey(KeyPair keyPair) {
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
        return rsaPrivateKey.getEncoded();
    }

    /**
     * 公钥字符串转PublicKey实例
     * @param publicKey 公钥字符串
     * @return          PublicKey
     * @throws Exception e
     */
    public static PublicKey getPublicKey(String publicKey) throws Exception {
        byte[] publicKeyBytes = Base64.decodeBase64(publicKey.getBytes());
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(keySpec);
    }

    /**
     * 私钥字符串转PrivateKey实例
     * @param privateKey  私钥字符串
     * @return PrivateKey
     * @throws Exception e
     */
    public static PrivateKey getPrivateKey(String privateKey) throws Exception {
        byte[] privateKeyBytes = Base64.decodeBase64(privateKey.getBytes());
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);
    }

    /**
     * 获取公钥字符串
     * @param keyPair KeyPair
     * @return  公钥字符串
     */
    public static String getPublicKeyString(KeyPair keyPair){
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  // 得到公钥
        String s = new String(publicKey.getEncoded());
        log.info("不编码的数据:{}",s);
        return new String(org.apache.commons.codec.binary.Base64.encodeBase64(publicKey.getEncoded()));
    }

    /**
     * 获取私钥字符串
     * @param keyPair  KeyPair
     * @return 私钥字符串
     */
    public static String getPrivateKeyString(KeyPair keyPair){
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();   // 得到私钥
        return new String(org.apache.commons.codec.binary.Base64.encodeBase64((privateKey.getEncoded())));
    }


    /**
     * 公钥加密
     * @param data        明文
     * @param publicKey   公钥
     * @return            密文
     */
    public static String publicEncrypt(String data, RSAPublicKey publicKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] bytes = rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), publicKey.getModulus().bitLength());
            return new String(org.apache.commons.codec.binary.Base64.encodeBase64(bytes));
        } catch (Exception e) {
            throw new RuntimeException("加密字符串[" + data + "]时遇到异常"+  e.getMessage());
        }
    }

    /**
     * 私钥解密
     * @param data        密文
     * @param privateKey  私钥
     * @return            明文
     */
    public static String privateDecrypt(String data, RSAPrivateKey privateKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);

            String str = new String(Base64.decodeBase64(data), "UTF-8");
            log.info("Base64,{}",str);
            return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE,
                    Base64.decodeBase64(data), privateKey.getModulus().bitLength()), CHARSET);
        } catch (Exception e) {
            throw new RuntimeException("privateKey解密字符串[" + data + "]时遇到异常"+  e.getMessage());
        }
    }


    /**
     * 私钥加密
     * @param content 明文
     * @param privateKey 私钥
     * @return 密文
     */
    public static String encryptByPrivateKey(String content, RSAPrivateKey privateKey){

        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            byte[] bytes = rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE,content.getBytes(CHARSET), privateKey.getModulus().bitLength());
            return new String(org.apache.commons.codec.binary.Base64.encodeBase64(bytes));
        } catch (Exception e) {
            throw new RuntimeException("privateKey加密字符串[" + content + "]时遇到异常" +  e.getMessage());
        }
    }

    /**
     * 公钥解密
     * @param content  密文
     * @param publicKey 私钥
     * @return  明文
     */
    public static String decryByPublicKey(String content, RSAPublicKey publicKey){
        try {

            //Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 在android项目中要使用这种方式加密(相当于jdk的RSA) 而不是RSA JDK和android 默认标准不一样 具体可以查下资料
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            log.info("Base64.getDecoder().decode(content).toString(),{}",Base64.decodeBase64(content).toString());
            return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(content), publicKey.getModulus().bitLength()), CHARSET);
        } catch (Exception e) {
            throw new RuntimeException("publicKey解密字符串[" + content + "]时遇到异常" +e.getMessage());
        }
    }

    public static RSAPublicKey getRSAPublicKeyByString(String publicKey){
        try {
//            org.apache.commons.codec.binary.Base64.decodeBase64(publicKeyString)
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(org.apache.commons.codec.binary.Base64.decodeBase64(publicKey));
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return (RSAPublicKey)keyFactory.generatePublic(keySpec);
        } catch (Exception e) {
            throw new RuntimeException("String转PublicKey出错" + e.getMessage());
        }
    }







//

    public static RSAPrivateKey getRSAPrivateKeyByString(String privateKey){
        try {
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return (RSAPrivateKey)keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        } catch (Exception e) {
            throw new RuntimeException("String转PrivateKey出错" + e.getMessage());
        }
    }


    //rsa切割解码  , ENCRYPT_MODE,加密数据   ,DECRYPT_MODE,解密数据
    private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize) {
        int maxBlock = 0;  //最大块
        if (opmode == Cipher.DECRYPT_MODE) {
            maxBlock = keySize / 8;
        } else {
            maxBlock = keySize / 8 - 11;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] buff;
        int i = 0;
        try {
            while (datas.length > offSet) {
                if (datas.length - offSet > maxBlock) {
                    //可以调用以下的doFinal()方法完成加密或解密数据:
                    buff = cipher.doFinal(datas, offSet, maxBlock);
                } else {
                    buff = cipher.doFinal(datas, offSet, datas.length - offSet);
                }
                out.write(buff, 0, buff.length);
                i++;
                offSet = i * maxBlock;
            }
        } catch (Exception e) {
            throw new RuntimeException("加解密阀值为[" + maxBlock + "]的数据时发生异常: " + e.getMessage());
        }
        byte[] resultDatas = out.toByteArray();
        IOUtils.closeQuietly(out);
        return resultDatas;
    }

    public static void main(String[] args) {
//        getKeyPair(1024);
//
//
//
//        RSAPublicKey rsaPublicKeyByString = getRSAPublicKeyByString(RequestDecryptionUtil.publicKey);
//
//        String aa = publicEncrypt("{\"key\":\"eViXqtVyTMPRpWVl\",\"keyVI\":\"QH9hKMwqHpcTL5Fm\",\"time\":1716531679199}", rsaPublicKeyByString);
//
//        System.out.printf(aa);
//
        RSAPrivateKey rsaPrivateKeyByString = getRSAPrivateKeyByString(RequestDecryptionUtil.privateKey);

        String s = privateDecrypt(aa, rsaPrivateKeyByString);

        System.out.printf(s);
//
try {
            s = RSAUtils.encryptByPublicKey(RequestDecryptionUtil.publicKey, "123");
            System.out.println(s);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
//        try {
//            String s1 = RSAUtils.decryptByPrivateKey(RequestDecryptionUtil.privateKey, aa);
//            System.out.println(s1);
//        } catch (Exception e) {
//            throw new RuntimeException(e);
//        }
//
//
//
//
//        String s = null;
//        try {
//            s = RSAUtils.encryptByPublicKey(RequestDecryptionUtil.publicKey, "123");
//            System.out.println(s);
//        } catch (Exception e) {
//            throw new RuntimeException(e);
//        }
//        RSAPrivateKey rsaPrivateKeyByString = getRSAPrivateKeyByString(RequestDecryptionUtil.privateKey);
//
//        String b = privateDecrypt(s, rsaPrivateKeyByString);
//
//        System.out.printf(b);

    }
}

二、AES工具类

package com.ruoyi.common.utils.rsa;

import lombok.Data;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.nio.charset.StandardCharsets;
import java.security.Security;
import java.util.Base64;



@Data
public class AES256Util {

    private static final String AES = "AES";
    /**
     * 初始向量IV, 初始向量IV的长度规定为128位16个字节, 初始向量的来源为随机生成.
     */
    /**"AES/CBC/NoPadding"
     * 加密解密算法/加密模式/填充方式
     */
    private static final String CIPHER_ALGORITHM = "AES/CBC/NoPadding";

    private static final Base64.Encoder base64Encoder = java.util.Base64.getEncoder();
    private static final Base64.Decoder base64Decoder = java.util.Base64.getDecoder();

    /**
     * key的长度,Wrong key size: must be equal to 128, 192 or 256
     * 传入时需要16、24、36
     */
    private static final int KEY_LENGTH = 16 * 8;

    //通过在运行环境中设置以下属性启用AES-256支持
    static {
        Security.setProperty("crypto.policy", "unlimited");
    }
    /*
     * 解决java不支持AES/CBC/PKCS7Padding模式解密
     */
    static {
        Security.addProvider(new BouncyCastleProvider());
    }



    private static final int BLOCK_SIZE = 16; // AES block size, in bytes


// 后台加密使用此方法  NoPadding  key  iv  内容为16位
    public static String encrypt(String key, String iv, String plaintext) throws Exception {
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));

        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);

        byte[] encryptedBytes = cipher.doFinal(pad(plaintext.getBytes(StandardCharsets.UTF_8), BLOCK_SIZE));
        return base64Encoder.encodeToString(encryptedBytes);
    }


    // Padding method to be compatible with NoPadding
    private static byte[] pad(byte[] data, int size) {
        int length = data.length;
        if (length % size == 0) {
            return data;
        }
        byte[] padded = new byte[size * (length / size + 1)];
        System.arraycopy(data, 0, padded, 0, length);
        return padded;
    }





//    /**
//     * AES加密
//     */
//    public static String encode(String key, String content,String keyVI) {
//        try {
//            javax.crypto.SecretKey secretKey = new javax.crypto.spec.SecretKeySpec(key.getBytes(), AES);
//            javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(CIPHER_ALGORITHM);
//            cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, secretKey, new javax.crypto.spec.IvParameterSpec(keyVI.getBytes()));
//            // 获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
//            byte[] byteEncode = content.getBytes(java.nio.charset.StandardCharsets.UTF_8);
//            // 根据密码器的初始化方式加密
//            byte[] byteAES = cipher.doFinal(byteEncode);
//            // 将加密后的数据转换为字符串
//            return base64Encoder.encodeToString(byteAES);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return null;
//    }
//
//
//    /**
//     * 获取key
//     */
//    public static String getKey() {
//        int length = KEY_LENGTH / 8;
//        StringBuilder uid = new StringBuilder(length);
//        //产生16位的强随机数
//        Random rd = new SecureRandom();
//        for (int i = 0; i < length; i++) {
//            //产生0-2的3位随机数
//            switch (rd.nextInt(3)) {
//                case 0:
//                    //0-9的随机数
//                    uid.append(rd.nextInt(10));
//                    break;
//                case 1:
//                    //ASCII在65-90之间为大写,获取大写随机
//                    uid.append((char) (rd.nextInt(26) + 65));
//                    break;
//                case 2:
//                    //ASCII在97-122之间为小写,获取小写随机
//                    uid.append((char) (rd.nextInt(26) + 97));
//                    break;
//                default:
//                    break;
//            }
//        }
//        return uid.toString();
//    }

    /**
     * AES解密
     */
    public static String decode(String key, String content,String keyVI) {
        try {
            javax.crypto.SecretKey secretKey = new javax.crypto.spec.SecretKeySpec(key.getBytes(), AES);
            javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(CIPHER_ALGORITHM);
            cipher.init(javax.crypto.Cipher.DECRYPT_MODE, secretKey, new javax.crypto.spec.IvParameterSpec(keyVI.getBytes(StandardCharsets.UTF_8)));
            // 将加密并编码后的内容解码成字节数组
            byte[] byteContent = org.apache.commons.codec.binary.Base64.decodeBase64(content.getBytes());;
            // 解密
            byte[] byteDecode = cipher.doFinal(byteContent);
            return new String(byteDecode);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

//这个是正确的
//    public static String decode(String key, String content,String keyVI){
//      try {
//        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
//        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
//        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(keyVI.getBytes(StandardCharsets.UTF_8)));
//        byte[] original = cipher.doFinal(Base64.getDecoder().decode(content));
//      return new String(original, StandardCharsets.UTF_8);
//                } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return null;
//    }





//    /**
//     * AES加密ECB模式PKCS7Padding填充方式
//     * @param str 字符串
//     * @param key 密钥
//     * @return 加密字符串
//     * @throws Exception 异常信息
//     */
//    public static String aes256ECBPkcs7PaddingEncrypt(String str, String key) throws Exception {
//        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
//        byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
//        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, AES));
//        byte[] doFinal = cipher.doFinal(str.getBytes(StandardCharsets.UTF_8));
//        return new String(Base64.getEncoder().encode(doFinal));
//    }
//
//    /**
//     * AES解密ECB模式PKCS7Padding填充方式
//     * @param str 字符串
//     * @param key 密钥
//     * @return 解密字符串
//     * @throws Exception 异常信息
//     */
//    public static String aes256ECBPkcs7PaddingDecrypt(String str, String key) throws Exception {
//        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
//        byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
//        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, AES));
//        byte[] doFinal = cipher.doFinal(Base64.getDecoder().decode(str));
//        return new String(doFinal);
//    }

    public static void main(String[] args) {
//        String qw = encode("8L9UjJ3ImkkKoCSy", "y8CRKjEfWFxFN2or", "y8CRKjEfWFxFN2or");
//        System.out.println(qw);
//
//        String qw1 = decode("8L9UjJ3ImkkKoCSy", qw, "y8CRKjEfWFxFN2or");
//        System.out.println(qw1);
    }
}

三、解密工具类

package com.ruoyi.common.utils.rsa;

import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.security.interfaces.RSAPrivateKey;
import java.util.Objects;


@Component
public class RequestDecryptionUtil {

    private static RequestDecryptionUtil requestDecryptionUtil;
    @Resource
    private  ConfigurationInfo appConfig;


    @PostConstruct
    public void init() {
        requestDecryptionUtil = this;
        requestDecryptionUtil.appConfig = this.appConfig;
    }
//    public final static String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDG3U7/0X2XOkSijPjCCFjOX2hGNb/BOW4Asx6S9Lx84ovzeFzFKy1rOLH2EpEQwjpC958Xro4neWpzXXIn8Fahun1B2qK2wggUsA3ylxpCxI53lwXvvC6rN6IU83MueInAwhVjIpqj/evf5LsZ9yp63z1wXVO7VmGYGb+kd6jOAwIDAQAB";
//    public final static String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMbdTv/RfZc6RKKM+MIIWM5faEY1v8E5bgCzHpL0vHzii/N4XMUrLWs4sfYSkRDCOkL3nxeujid5anNdcifwVqG6fUHaorbCCBSwDfKXGkLEjneXBe+8Lqs3ohTzcy54icDCFWMimqP969/kuxn3KnrfPXBdU7tWYZgZv6R3qM4DAgMBAAECgYEAomNdezCKKc9+9G3BRFCklAD8mTiS2SoYVaHuuXn34NLuDWaf+rGDaSbmy1Xl95VjFgQ2eZQkqL9Q2dvYuBxd4EiNDngkBMfFSmN5z9LqIeE8BAeUSoIfhCaXE5QEwL8765tHitveapmKmOx8NMt4HSUw6iMlimW+E+3qypL/HAECQQD5zGsshI1jN1QvlBCpJjabC5Xlf+HxSWqOZ67AQzRfKccKp8XU8/nnzrUac5xUxwi5c9NfqXuuxxYrRCda3oqDAkEAy80ucbexMBREZF3amPfBe737X7QBP3jdNYt7D5ObP+iU+jYnDh5Wstau4TdQ5kXwBunvP+j7sUiHCl4OvH9WgQJAQGpaaMx1uVQXPX2tHjFge3LtYJUtqo8ID1jlU2cBJlkbnr/M4DFaDFDdmsidU69PrKMVquGFp3hnWxjkHSauCQJAW0Evd6nZw/5/NTW1KONfFmpWAV9XY7VZz5z56FqenHonIvZWfILnLULloWCkb8eHF4FuKH7JHHOuS90b2hlmgQJAV/BWjPOD3x25AA3+2iIKM2BFCWHPOECncxNyNzG3j/D6iVQEytfqMSX7kDOrTL+cNp+GvaNm2eKKlojipOT7Mg==";
//

//    public final static String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzxEEl/TfgaYVGF0CtsPX\n" +
//            "Ylx3ksNZe52DJROhRoQMaRB665ozh7KtDx79zXZL47vfvh0ivlWcMPgqBmiz/s3i\n" +
//            "AWmWOVd6aTUmkkDC4hAWSpkk01o5Pi+c6YtGFe1uJv+4vV9EBpW2vN2Lgg/+kAc+\n" +
//            "4Vx1cD5FBvJdKaMsG6ei9hRl56VshW8xqSU28DNfhl/kWjZ12S20ZwTDjUP5YhfF\n" +
//            "2OYaFLYxING86EX/Nh0RcKoQqqlDwAIxgUJx9uhMziUfwaj1oX4PgAdGkJS1VK7k\n" +
//            "rZZfde7Vc6Gi6kuaDOZmtgjWM1KpJP+fnKHj9mDnDN3joAjhCwWdtTldyWDm35mJ\n" +
//            "PQIDAQAB";

//    public final static String privateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDPEQSX9N+BphUY\n" +
//            "XQK2w9diXHeSw1l7nYMlE6FGhAxpEHrrmjOHsq0PHv3Ndkvju9++HSK+VZww+CoG\n" +
//            "aLP+zeIBaZY5V3ppNSaSQMLiEBZKmSTTWjk+L5zpi0YV7W4m/7i9X0QGlba83YuC\n" +
//            "D/6QBz7hXHVwPkUG8l0poywbp6L2FGXnpWyFbzGpJTbwM1+GX+RaNnXZLbRnBMON\n" +
//            "Q/liF8XY5hoUtjEg0bzoRf82HRFwqhCqqUPAAjGBQnH26EzOJR/BqPWhfg+AB0aQ\n" +
//            "lLVUruStll917tVzoaLqS5oM5ma2CNYzUqkk/5+coeP2YOcM3eOgCOELBZ21OV3J\n" +
//            "YObfmYk9AgMBAAECggEAR0KaDBmPmbSoadwIhRFc3FLqK63i67HHYkkhJX1oL/gl\n" +
//            "9VL6DOcmu590xPLDJzqOw4SPYmVf/VJKVC5QU45TCx1lP5KlY/OQtKBo8ReMNFwD\n" +
//            "2mCgdpA4Nf9iPUWatP0ofLN+W63GV7T+v+H1P2fe8fu5xskHRF7ARQYMte+5G2pG\n" +
//            "rXrxG0I0ovAX6SRtVPYJ7d1VjNzK7TaPLTVPsX8aRK1ZTCygsBdfbECn9c7yfvov\n" +
//            "BtknrHEKVBK1oCXfJsjVpHLUXChKBB7K8Ozj04JugqV+d7scVOpKph+vft1RDhel\n" +
//            "fdLocQ2ifsNh7CKJjKbRLj5GW7AQUG89Yqfx849NWQKBgQD6AlUNrnDzLqD6RQuh\n" +
//            "6NJK3ab6c49FK2HOG166naNIJJx8KCeGy7ocWXkgyl5Wtf+MCB9WnP4PWb+uC4iO\n" +
//            "kUpUHkPmUQn3j7efxV1h6B/KhMHlmeGfJbNz37HaNUkl50RAVTRlO/GEE/1RlVza\n" +
//            "HyXFXgeujUC8/ILgy16+DYX2VwKBgQDUB0GhfOZ/+xwex6n4qvoCgLkfV4SDJEhx\n" +
//            "9oJ2a9f+FNEesKCW5GF6sllopHb3xfDYkl+g19J0aQ9J0sWQvMCvM7M7rwTPlfOh\n" +
//            "zYLGlQJmlO60r9WvQWRwR5JmB9J3I1gaChAelxp2ScMkcXI47rbCDoZa2q4Ej5Vk\n" +
//            "YqwvADx4iwKBgQCdLDQuarllmK3pSNj8S/NQz7I3B8lNUe2l9n0CUzIgm6upPlFD\n" +
//            "I/b39aP54l+WocprTXvuJrpuCh1AHM4X2u1gnrpPJClg8oAdOKXxdE3wMq/3WVuH\n" +
//            "gtsjgME+DnvTEWZOD4LmFd5LC4oY7Q63rhc/0lKAARtu9EyPaCtCzhum9wKBgBrR\n" +
//            "+ClXRUj3GK2EECoWZp2ebsxaI7b7Bfb0ebhFGANZ2sIJEadEqFf+63RjKXFaJoce\n" +
//            "rN4JruNuzrJF6RvP5IfFAG0STId9rl3PQzWfb7hOKovMmjkbCntxckFZx/OuEtzo\n" +
//            "XPWho4VG+1pGx24QNCoD8FbZxp1pFDqoiKNBYmTVAoGBANKtrCkWvoxLuwUj6hhG\n" +
//            "ml+I4uweiOBt412GOPTsWkCRXmanWAsIm7FsGPtZHCz3b9OkGZNBzGtpGSPfXzog\n" +
//            "NdEQfyCDuAKNT4LlVZBPDjazA3aoijaC+4jt+TQP0DsQY9k+y/IL9kx/tvZs4NBy\n" +
//            "KJS0DIosnuo2hl51F4b9o/o5";


    private String privateKey;

    private final static Integer timeout = 60000;

    /**
     *
     * @param sym RSA 密文
     * @param asy AES 密文
     * @param clazz 接口入参类
     * @return Object
     */
    public static <T> Object getRequestDecryption(String sym, String asy, Class<T> clazz){
        //验证密钥
        try {
            //解密RSA
            RSAPrivateKey rsaPrivateKey = ActivityRSAUtil.getRSAPrivateKeyByString(requestDecryptionUtil.appConfig.getPrivateKey());
            String RSAJson = ActivityRSAUtil.privateDecrypt(sym, rsaPrivateKey);

            RSADecodeData rsaDecodeData = JSONObject.parseObject(RSAJson, RSADecodeData.class);
            boolean isTimeout = Objects.nonNull(rsaDecodeData)  && Objects.nonNull(rsaDecodeData.getTime())
                    && System.currentTimeMillis() -  rsaDecodeData.getTime() < timeout;
            if (!isTimeout){
                throw new RuntimeException("Request timed out, please try again."); //请求超时
            }
            //解密AES
            String AESJson = AES256Util.decode(rsaDecodeData.getKey(),asy,rsaDecodeData.getKeyVI());
            System.out.println("AESJson: "+AESJson);
            return JSONObject.parseObject(AESJson,clazz);
        } catch (Exception e) {
            throw new RuntimeException("RSA decryption Exception:  " +e.getMessage());
        }
    }

    public static JSONObject getRequestDecryption(String sym, String asy){
        //验证密钥
        try {
            //解密RSA
            RSAPrivateKey rsaPrivateKey = ActivityRSAUtil.getRSAPrivateKeyByString(requestDecryptionUtil.appConfig.getPrivateKey());
            String RSAJson = ActivityRSAUtil.privateDecrypt(sym, rsaPrivateKey);
            RSADecodeData rsaDecodeData = JSONObject.parseObject(RSAJson, RSADecodeData.class);
//            boolean isTimeout = Objects.nonNull(rsaDecodeData)  && Objects.nonNull(rsaDecodeData.getTime()) && System.currentTimeMillis() -  rsaDecodeData.getTime() < timeout;
//            if (!isTimeout){
//                throw new RuntimeException("Request timed out, please try again."); //请求超时
//            }
            //解密AES
            String AESJson = AES256Util.decode(rsaDecodeData.getKey(),asy,rsaDecodeData.getKeyVI());
            System.out.println("AESJson: "+AESJson);
            return JSONObject.parseObject(AESJson);
        } catch (Exception e) {
            throw new RuntimeException("RSA decryption Exception:  " +e.getMessage());
        }
    }
}

四、自定义注解

package com.ruoyi.common.utils.rsa;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestRSA {
}

五、aes加密实体类

package com.ruoyi.common.utils.rsa;

import lombok.Data;

@Data
public class RSADecodeData {

    private String key;

    private String keyVI;

    private Long time;


}

六、加密的请求参数

package com.ruoyi.common.utils.rsa;

import lombok.Data;

@Data
public class RSAEncodeData {
    private String asy;
    private String sym;
}

七、这里使用拦截器解密

package com.ruoyi.common.utils.rsa;


import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.filter.RepeatedlyRequestWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;

@Slf4j
@Component
public class RSAModuleInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            RequestRSA annotation = method.getAnnotation(RequestRSA.class);
            if (Objects.nonNull(annotation)) {
                byte[] bodyBytes = StreamUtils.copyToByteArray(request.getInputStream());
                String body = new String(bodyBytes, request.getCharacterEncoding());
                log.info("[ WebInterceptor ] >> preHandle  requestUrI:{}  requestBody:{}", request.getRequestURI(), body);
                JSONObject jsonObject = JSONObject.parseObject(body);
                String asy = jsonObject.get("asy").toString();
                String sym = jsonObject.get("sym").toString();
                JSONObject decryption = RequestDecryptionUtil.getRequestDecryption(sym, asy);
//                Class<?>[] parameterTypes = method.getParameterTypes();
//                // 打印方法参数类型
//                for (Class<?> parameterType : parameterTypes) {
//                    System.out.println(parameterType.getName());
//                    Class<? extends Class> aClass = parameterType.getClass();
                    Object o = JSONObject.parseObject(decryption.toJSONString(), aClass);
//                    log.info("[ 111111111 ] >> preHandle  requestUrI:{} ", aClass);
//
//
//                }
                ObjectMapper objectMapper = new ObjectMapper();

                // JSONObject转Map<String, Object>
                Map<String, Object> map = (Map<String, Object>)decryption.getInnerMap();

//                Set<Map.Entry<String, Object>> entries = decryption.entrySet();
//                Map<String,Object>  map = new HashMap<>();
//                map.put("username","admin");
                String s = objectMapper.writeValueAsString(map);
                ((RepeatedlyRequestWrapper) request).setBody(s.getBytes());





            }
            return true;
        }
        return true;
    }


//    List<Object> argList = new ArrayList<>();
//    Parameter[] parameters = method.getParameters();
//        for (int i = 0; i < parameters.length; i++) {
//        //将RequestBody注解修饰的参数作为请求参数
            RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
            if (requestBody != null) {
                argList.add(args[i]);
            }
//        argList.add(args[i]);
//    }
//        if (argList.size() == 0) {
//        return null;
//    } else if (argList.size() == 1) {
//        return argList.get(0);
//    } else {
//        return argList;
//    }



}

八、可以修改请求参数的request

package com.ruoyi.common.filter;

import com.ruoyi.common.utils.http.HttpHelper;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * 构建可重复读取inputStream的request
 * 
 * @author ruoyi
 */
public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper
{
    private  byte[] body;

    public void setBody(byte[] body){
        this.body = body;
    }

    public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException
    {
        super(request);
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

        body = HttpHelper.getBodyString(request).getBytes("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 int read() throws IOException
            {
                return bais.read();
            }

            @Override
            public int available() throws IOException
            {
                return body.length;
            }

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

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

            @Override
            public void setReadListener(ReadListener readListener)
            {

            }
        };
    }
}

九、RSA工具类

package com.ruoyi.common.utils.rsa;

import org.apache.commons.codec.binary.Base64;
import org.springframework.context.annotation.Bean;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class RSAUtils {
    // Rsa 私钥 也可固定秘钥对 若依原写法(不安全)
    public static String privateKeys = "";
    private static String publicKeyStr = "";
    private static String privateKeyStr = "";
    private static final RSAKeyPair rsaKeyPair = new RSAKeyPair();

    /**
     * 私钥解密
     *
     * @param text 待解密的文本
     * @return 解密后的文本
     */
    public static String decryptByPrivateKey(String text) throws Exception {
        return decryptByPrivateKey(rsaKeyPair.getPrivateKey(), text);
    }

    /**
     * 公钥解密
     *
     * @param publicKeyString 公钥
     * @param text            待解密的信息
     * @return 解密后的文本
     */
    public static String decryptByPublicKey(String publicKeyString, String text) throws Exception {
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyString));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        byte[] result = cipher.doFinal(Base64.decodeBase64(text));
        return new String(result);
    }

    /**
     * 私钥加密
     *
     * @param privateKeyString 私钥
     * @param text             待加密的信息
     * @return 加密后的文本
     */
    public static String encryptByPrivateKey(String privateKeyString, String text) throws Exception {
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        byte[] result = cipher.doFinal(text.getBytes());
        return Base64.encodeBase64String(result);
    }

    /**
     * 私钥解密
     *
     * @param privateKeyString 私钥
     * @param text             待解密的文本
     * @return 解密后的文本
     */
    public static String decryptByPrivateKey(String privateKeyString, String text) throws Exception {
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] result = cipher.doFinal(Base64.decodeBase64(text));
        return new String(result);
    }

    /**
     * 公钥加密
     *
     * @param publicKeyString 公钥
     * @param text            待加密的文本
     * @return 加密后的文本
     */
    public static String encryptByPublicKey(String publicKeyString, String text) throws Exception {
        X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyString));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] result = cipher.doFinal(text.getBytes());
        return Base64.encodeBase64String(result);
    }

    public static RSAPublicKey getRSAPublicKeyByString(String publicKey){
        try {
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(java.util.Base64.getDecoder().decode(publicKey));
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return (RSAPublicKey)keyFactory.generatePublic(keySpec);
        } catch (Exception e) {
            throw new RuntimeException("String转PublicKey出错" + e.getMessage());
        }
    }



    /**
     * 构建RSA密钥对
     *
     * @return 生成后的公私钥信息
     */
    @Bean
    public void generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
        String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());
        String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
        rsaKeyPair.setPrivateKey(privateKeyString);
        rsaKeyPair.setPublicKey(publicKeyString);
        publicKeyStr = publicKeyString;
        privateKeyStr = privateKeyString;
    }


    public static String getPublicKey() {
        return publicKeyStr;
    }

    public static String getPrivateKey() {
        return privateKeyStr;
    }

    public static RSAKeyPair rsaKeyPair() {
        return rsaKeyPair;
    }

    /**
     * RSA密钥对对象
     */
    public static class RSAKeyPair {
        private String publicKey;
        private String privateKey;

        public void setPublicKey(String publicKey) {
            this.publicKey = publicKey;
        }

        public void setPrivateKey(String privateKey) {
            this.privateKey = privateKey;
        }

        public RSAKeyPair() {

        }

        public RSAKeyPair(String publicKey, String privateKey) {
            this.publicKey = publicKey;
            this.privateKey = privateKey;
        }

        public String getPublicKey() {
            return publicKey;
        }

        public String getPrivateKey() {
            return privateKey;
        }
    }

    public static void main(String[] args) {
//        String s = null;
//        try {
//            s = encryptByPublicKey(RequestDecryptionUtil.publicKey, "123");
//            System.out.println(s);
//        } catch (Exception e) {
//            throw new RuntimeException(e);
//        }
//        try {
//            String s1 = decryptByPrivateKey(RequestDecryptionUtil.privateKey, s);
//            System.out.println(s1);
//        } catch (Exception e) {
//            throw new RuntimeException(e);
//        }
    }
}

十、前端加密需要用到的js

import JSEncrypt from 'jsencrypt'

// import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'
import CryptoJS from 'crypto-js'
import de from "element-ui/src/locale/lang/de";
const Base64 = require("js-base64").Base64


const publicKey= process.env.VUE_APP_PUBLICKEY;

export function rsaEncrypt(txt) {
  const encryptor = new JSEncrypt()
  encryptor.setPublicKey(publicKey) // 设置公钥
  return encryptor.encrypt(txt) // 对数据进行加密
}



/*
 * AES加密 :字符串 key iv  返回base64
 */
//加密方法
export function aesEncrypt(word, key, iv) {
  const data = JSON.stringify(word);
  const srcs = CryptoJS.enc.Utf8.parse(data);
  // /**
  //  * CipherOption, 加密的一些选项:
  //  *   mode: 加密模式, 可取值(CBC, CFB, CTR, CTRGladman, OFB, ECB), 都在 CryptoJS.mode 对象下
  //  *   padding: 填充方式, 可取值(Pkcs7, AnsiX923, Iso10126, Iso97971, ZeroPadding, NoPadding), 都在 CryptoJS.pad 对象下
  //  *   iv: 偏移量, mode === ECB 时, 不需要 iv
  //  *     返回的是一个加密对象
  //  */
  var key = CryptoJS.enc.Utf8.parse(key); // 密钥
  var message = srcs;
  var encrypted = CryptoJS.AES.encrypt(message, key, {
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7,
    iv: CryptoJS.enc.Utf8.parse(iv) // 初始化向量
  });
  return  encrypted.toString();
}



/**
 * 获取16位随机码AES
 * @returns {string}
 */
export function get16RandomNum() {
  var chars = [       '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K', 'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
    'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'
  ]
  var nums = ''
  //这个地方切记要选择16位,因为美国对密钥长度有限制,选择32位的话加解密会报错,需要根据jdk版本去修改相关jar包,有点恼火,选择16位就不用处理。
  for (var i = 0; i < 16; i++) {
    var id = parseInt(Math.random() * 61)
    nums += chars[id]
  }
  return nums
}

十一、前端拦截器对请求统一加密

import axios from 'axios'
import { Notification, MessageBox, Message, Loading } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { tansParams, blobValidate } from "@/utils/ruoyi";
import cache from '@/plugins/cache'
import { saveAs } from 'file-saver'
import {aesEncrypt, get16RandomNum, rsaEncrypt} from "@/api/encipher/encipher";

let downloadLoadingInstance;
// 是否显示重新登录
export let isRelogin = { show: false };

axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
  // axios中请求配置有baseURL选项,表示请求URL公共部分
  baseURL: process.env.VUE_APP_BASE_API,
  // 超时
  timeout: 5 * 60 * 1000
})

// request拦截器
service.interceptors.request.use(config => {
  // 是否需要设置 token
  const isToken = (config.headers || {}).isToken === false
  // 是否需要防止数据重复提交
  const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
  if (getToken() && !isToken) {
    config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
  }
  // get请求映射params参数
  if (config.method === 'get' && config.params) {
    let url = config.url + '?' + tansParams(config.params);
    url = url.slice(0, -1);
    config.params = {};
    config.url = url;
  }
  if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {

    let key = get16RandomNum();
    let keyVI = get16RandomNum();
    let time = Date.now();
    let  param = {
      "key":key,
      "keyVI":keyVI,
      "time":time
    }
    let data =  typeof config.data === 'object' ? JSON.stringify(config.data) : config.data
    let asy = aesEncrypt(config.data,key,keyVI);
    //用登陆后后端生成并返回给前端的的RSA密钥对的公钥将AES16位密钥进行加密
    let sym = rsaEncrypt(JSON.stringify(param))
    console.log("加密数据")
    console.log(data)
    console.log(asy)
    console.log(sym)
    let paramData = {
      "asy":asy,
      "sym":sym
    }
    console.log(paramData)
    console.log(JSON.stringify(paramData))
    config.data = paramData;
    const requestObj = {
      url: config.url,
      data: paramData,
      time: new Date().getTime()
    }
    console.log(requestObj)
    const sessionObj = cache.session.getJSON('sessionObj')
    if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
      cache.session.setJSON('sessionObj', requestObj)
    } else {
      const s_url = sessionObj.url;                  // 请求地址
      const s_data = sessionObj.data;                // 请求数据
      const s_time = sessionObj.time;                // 请求时间
      const interval = 1000;                         // 间隔时间(ms),小于此时间视为重复提交
      if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
        const message = '数据正在处理,请勿重复提交';
        console.warn(`[${s_url}]: ` + message)
        return Promise.reject(new Error(message))
      } else {
        cache.session.setJSON('sessionObj', requestObj)
      }
    }
  }
  return config
}, error => {
  console.log(error)
  Promise.reject(error)
})

// 响应拦截器
service.interceptors.response.use(res => {
  // 未设置状态码则默认成功状态
  const code = res.data.code || 200;
  // 获取错误信息
  const msg = errorCode[code] || res.data.msg || errorCode['default']
  // 二进制数据则直接返回
  if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
    return res.data
  }
  if (code === 401) {
    if (!isRelogin.show) {
      isRelogin.show = true;
      MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
        confirmButtonText: '重新登录',
        cancelButtonText: '取消',
        type: 'warning'
      }
      ).then(() => {
        isRelogin.show = false;
        store.dispatch('LogOut').then(() => {
          // 如果是登录页面不需要重新加载
          if (window.location.hash.indexOf("#/login") != 0) {
            location.href = '/index';
          }
        })
      }).catch(() => {
        isRelogin.show = false;
      });
    }
    return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
  } else if (code === 500) {
    Message({
      message: msg,
      type: 'error'
    })
    return Promise.reject(new Error(msg))
  } else if (code === 5000) {
    MessageBox.confirm(msg, '系统提示', {
      confirmButtonText: '确认',
      showCancelButton: false,
      type: 'warning'
    })
    return Promise.reject(new Error(msg))
  } else if (code == 7000) {
    return res.data
  }else if (code !== 200) {
    Notification.error({
      title: msg
    })
    return Promise.reject('error')
  } else {
    return res.data
  }
},
  error => {
    console.log('err' + error)
    let { message } = error;
    if (message == "Network Error") {
      message = "后端接口连接异常";
    }
    else if (message.includes("timeout")) {
      message = "系统接口请求超时";
    }
    else if (message.includes("Request failed with status code")) {
      message = "系统接口" + message.substr(message.length - 3) + "异常";
    }
    Message({
      message: message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)

// 通用下载方法
export function download(url, params, filename) {
  downloadLoadingInstance = Loading.service({ text: "正在下载数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", })
  return service.post(url, params, {
    transformRequest: [(params) => { return tansParams(params) }],
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    responseType: 'blob'
  }).then(async (data) => {
    const isLogin = await blobValidate(data);
    if (isLogin) {
      const blob = new Blob([data])
      saveAs(blob, filename)
    } else {
      const resText = await data.text();
      const rspObj = JSON.parse(resText);
      const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
      Message.error(errMsg);
    }
    downloadLoadingInstance.close();
  }).catch((r) => {
    console.error(r)
    Message.error('下载文件出现错误,请联系管理员!')
    downloadLoadingInstance.close();
  })
}

export default service

十二、为什么使用拦截器不使用aop

本来是使用aop实现解密逻辑的,但是项目中使用校验的注解,发现@Validated注解会先于aop执行参数校验,所有使用拦截器。

十三、Android中使用注意点

android 也可以使用上面的工具类,需要添加依赖,需要注意的是初始化Cipher的方式要变一下,否则安卓加密在web项目中无法解密.正常使用的话请求结果应该如图所示。

    implementation 'commons-codec:commons-codec:1.15'
    implementation 'org.bouncycastle:bcprov-jdk15on:1.69'
    implementation 'commons-io:commons-io:2.8.0'

总结

代码全部贴出来了,不仔细去讲解内容了,直接复制,拦截器这部分需要你自己添加到自己的配置文件中(如何集成拦截器知识自己查询)。所有的方法经过测试,不明白的可以留言。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值