十次方社交项目-接口加密4

一、搭建接口加密微服务

接口加解密请求参数的流程

 facb39e9b957a5ef79b592e075a5213a_1563096130123

二、创建tensquare_encrypt网关服务

在tensquare_parent父工程下新建tensquare_encrypt子模块,并按下面的步骤添加配置和代码

1. 在pom.xml文件中添加以下配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>tensquare_parent</artifactId>
        <groupId>com.tensquare</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>tensquare_encrypt</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>
    </dependencies>

</project>
View Code

2. 在resource文件夹下新建application.yml文件,并添加如下配置

server:
  port: 9013
spring:
  application:
    name: tensquare-encrypt
zuul:
  routes:
    tensquare-article:  #路由到文章微服务
      path: /article/** #配置请求URL的请求规则
      serviceId: tensquare-article  #指定Eureka注册中心的服务id
      strip-prefix: true    #所有的article请求都进行转发
      sentiviteHeaders:
      customSensitiveHeaders: true  #让zuul网关处理Cookeie和重定向
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:6868/eureka/
    instance:
      prefer-ip-address: true
View Code

3. 新建com.tensquare.encrypt包,并在包下新建启动类EncryptApplication,添加如下代码

package com.tensquare.encrypt;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class EncryptApplication {

    public static void main(String[] args) {
        SpringApplication.run(EncryptApplication.class,args);
    }
}
View Code

4. 将rsa相关的工具类复制到在com.tensquare.encrypt包下

 工具类的位置放在rsa和service文件夹下

  image

 Base64Utils

package com.tensquare.encrypt.rsa;


import java.io.*;


public class Base64Utils {
    /** */
    /**
     * 28.     * 文件读取缓冲区大小
     * 29.
     */
    private static final int CACHE_SIZE = 1024;

    /** */
    /**
     * 33.     * <p>
     * 34.     * BASE64字符串解码为二进制数据
     * 35.     * </p>
     * 36.     *
     * 37.     * @param base64
     * 38.     * @return
     * 39.     * @throws Exception
     * 40.
     */
    public static byte[] decode(String base64) throws Exception {
        return mBase64.decode(base64.getBytes());
    }

    /** */
    /**
     * 46.     * <p>
     * 47.     * 二进制数据编码为BASE64字符串
     * 48.     * </p>
     * 49.     *
     * 50.     * @param bytes
     * 51.     * @return
     * 52.     * @throws Exception
     * 53.
     */
    public static String encode(byte[] bytes) throws Exception {
        return new String(mBase64.encode(bytes));
    }

    /** */
    /**
     * 59.     * <p>
     * 60.     * 将文件编码为BASE64字符串
     * 61.     * </p>
     * 62.     * <p>
     * 63.     * 大文件慎用,可能会导致内存溢出
     * 64.     * </p>
     * 65.     *
     * 66.     * @param filePath 文件绝对路径
     * 67.     * @return
     * 68.     * @throws Exception
     * 69.
     */
    public static String encodeFile(String filePath) throws Exception {
        byte[] bytes = fileToByte(filePath);
        return encode(bytes);
    }

    /** */
    /**
     * 76.     * <p>
     * 77.     * BASE64字符串转回文件
     * 78.     * </p>
     * 79.     *
     * 80.     * @param filePath 文件绝对路径
     * 81.     * @param base64 编码字符串
     * 82.     * @throws Exception
     * 83.
     */
    public static void decodeToFile(String filePath, String base64) throws Exception {
        byte[] bytes = decode(base64);
        byteArrayToFile(bytes, filePath);
    }

    /** */
    /**
     * <p>
     * 文件转换为二进制数组
     * </p>
     *
     * @param filePath 文件路径
     * @return
     * @throws Exception
     */
    public static byte[] fileToByte(String filePath) throws Exception {
        byte[] data = new byte[0];
        File file = new File(filePath);
        if (file.exists()) {
            FileInputStream in = new FileInputStream(file);
            ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
            byte[] cache = new byte[CACHE_SIZE];
            int nRead = 0;
            while ((nRead = in.read(cache)) != -1) {
                out.write(cache, 0, nRead);
                out.flush();
            }
            out.close();
            in.close();
            data = out.toByteArray();
        }
        return data;
    }

    /** */
    /**
     * 118.     * <p>
     * 119.     * 二进制数据写文件
     * 120.     * </p>
     * 121.     *
     * 122.     * @param bytes 二进制数据
     * 123.     * @param filePath 文件生成目录
     * 124.
     */
    public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {
        InputStream in = new ByteArrayInputStream(bytes);
        File destFile = new File(filePath);
        if (!destFile.getParentFile().exists()) {
            destFile.getParentFile().mkdirs();
        }
        destFile.createNewFile();
        OutputStream out = new FileOutputStream(destFile);
        byte[] cache = new byte[CACHE_SIZE];
        int nRead = 0;
        while ((nRead = in.read(cache)) != -1) {
            out.write(cache, 0, nRead);
            out.flush();
        }
        out.close();
        in.close();
    }
    //新增-----------------------------------------

    private static char[] base64EncodeChars = new char[]{'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', '0', '1', '2', '3',
            '4', '5', '6', '7', '8', '9', '+', '/',};

    private static byte[] base64DecodeChars = new byte[]{-1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
            -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59,
            60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
            10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1,
            -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
            38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1,
            -1, -1};

    /**
     * 解密
     *
     * @param data
     * @return
     */
    public static byte[] decodeStr(byte[] data) {
//            byte[] data = str.getBytes();
        int len = data.length;
        ByteArrayOutputStream buf = new ByteArrayOutputStream(len);
        int i = 0;
        int b1, b2, b3, b4;

        while (i < len) {
            do {
                b1 = base64DecodeChars[data[i++]];
            } while (i < len && b1 == -1);
            if (b1 == -1) {
                break;
            }

            do {
                b2 = base64DecodeChars[data[i++]];
            } while (i < len && b2 == -1);
            if (b2 == -1) {
                break;
            }
            buf.write((int) ((b1 << 2) | ((b2 & 0x30) >>> 4)));

            do {
                b3 = data[i++];
                if (b3 == 61) {
                    return buf.toByteArray();
                }
                b3 = base64DecodeChars[b3];
            } while (i < len && b3 == -1);
            if (b3 == -1) {
                break;
            }
            buf.write((int) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2)));

            do {
                b4 = data[i++];
                if (b4 == 61) {
                    return buf.toByteArray();
                }
                b4 = base64DecodeChars[b4];
            } while (i < len && b4 == -1);
            if (b4 == -1) {
                break;
            }
            buf.write((int) (((b3 & 0x03) << 6) | b4));
        }
        return buf.toByteArray();
    }

}
View Code

 mBase64

package com.tensquare.encrypt.rsa;

/**
 * Created by Administrator on 2017/10/30.
 */

public class mBase64 {
    static final int CHUNK_SIZE = 76;
    static final byte[] CHUNK_SEPARATOR = "\r\n".getBytes();
    private static final int BASELENGTH = 255;
    private static final int LOOKUPLENGTH = 64;
    private static final int EIGHTBIT = 8;
    private static final int SIXTEENBIT = 16;
    private static final int TWENTYFOURBITGROUP = 24;
    private static final int FOURBYTE = 4;
    private static final int SIGN = -128;
    private static final byte PAD = 61;
    private static final byte[] base64Alphabet = new byte[255];
    private static final byte[] lookUpBase64Alphabet = new byte[64];

    public mBase64() {
    }

    private static boolean isBase64(byte octect) {
        return octect == 61 ? true : octect >= 0 && base64Alphabet[octect] != -1;
    }

    public static boolean isBase64(byte[] arrayOctect) {
        arrayOctect = discardWhitespace(arrayOctect);
        int length = arrayOctect.length;
        if (length == 0) {
            return true;
        } else {
            for (int i = 0; i < length; ++i) {
                if (!isBase64(arrayOctect[i])) {
                    return false;
                }
            }

            return true;
        }
    }

    static byte[] discardWhitespace(byte[] data) {
        byte[] groomedData = new byte[data.length];
        int bytesCopied = 0;
        byte[] packedData = data;
        int len$ = data.length;
        int i$ = 0;

        while (i$ < len$) {
            byte aByte = packedData[i$];
            switch (aByte) {
                default:
                    groomedData[bytesCopied++] = aByte;
                case 9:
                case 10:
                case 13:
                case 32:
                    ++i$;
            }
        }

        packedData = new byte[bytesCopied];
        System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
        return packedData;
    }

//    public static String encodeToString(byte[] bytes) {
//        byte[] encoded = encode(bytes);
//        return CodecSupport.toString(encoded);
//    }

    public static byte[] encodeChunked(byte[] binaryData) {
        return encode(binaryData, true);
    }

    public static byte[] encode(byte[] pArray) {
        return encode(pArray, false);
    }

    public static byte[] encode(byte[] binaryData, boolean isChunked) {
        long binaryDataLength = (long) binaryData.length;
        long lengthDataBits = binaryDataLength * 8L;
        long fewerThan24bits = lengthDataBits % 24L;
        long tripletCount = lengthDataBits / 24L;
        int chunckCount = 0;
        long encodedDataLengthLong;
        if (fewerThan24bits != 0L) {
            encodedDataLengthLong = (tripletCount + 1L) * 4L;
        } else {
            encodedDataLengthLong = tripletCount * 4L;
        }

        if (isChunked) {
            chunckCount = CHUNK_SEPARATOR.length == 0 ? 0 : (int) Math.ceil((double) ((float) encodedDataLengthLong / 76.0F));
            encodedDataLengthLong += (long) (chunckCount * CHUNK_SEPARATOR.length);
        }

        if (encodedDataLengthLong > 2147483647L) {
            throw new IllegalArgumentException("Input array too big, output array would be bigger than Integer.MAX_VALUE=2147483647");
        } else {
            int encodedDataLength = (int) encodedDataLengthLong;
            byte[] encodedData = new byte[encodedDataLength];
            int encodedIndex = 0;
            int nextSeparatorIndex = 76;
            int chunksSoFar = 0;

            byte k;
            byte l;
            byte b1;
            byte b2;
            int dataIndex;
            int i;
            byte val1;
            byte val2;
            for (i = 0; (long) i < tripletCount; ++i) {
                dataIndex = i * 3;
                b1 = binaryData[dataIndex];
                b2 = binaryData[dataIndex + 1];
                byte b3 = binaryData[dataIndex + 2];
                l = (byte) (b2 & 15);
                k = (byte) (b1 & 3);
                val1 = (b1 & -128) == 0 ? (byte) (b1 >> 2) : (byte) (b1 >> 2 ^ 192);
                val2 = (b2 & -128) == 0 ? (byte) (b2 >> 4) : (byte) (b2 >> 4 ^ 240);
                byte val3 = (b3 & -128) == 0 ? (byte) (b3 >> 6) : (byte) (b3 >> 6 ^ 252);
                encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
                encodedData[encodedIndex + 1] = lookUpBase64Alphabet[val2 | k << 4];
                encodedData[encodedIndex + 2] = lookUpBase64Alphabet[l << 2 | val3];
                encodedData[encodedIndex + 3] = lookUpBase64Alphabet[b3 & 63];
                encodedIndex += 4;
                if (isChunked && encodedIndex == nextSeparatorIndex) {
                    System.arraycopy(CHUNK_SEPARATOR, 0, encodedData, encodedIndex, CHUNK_SEPARATOR.length);
                    ++chunksSoFar;
                    nextSeparatorIndex = 76 * (chunksSoFar + 1) + chunksSoFar * CHUNK_SEPARATOR.length;
                    encodedIndex += CHUNK_SEPARATOR.length;
                }
            }

            dataIndex = i * 3;
            if (fewerThan24bits == 8L) {
                b1 = binaryData[dataIndex];
                k = (byte) (b1 & 3);
                val1 = (b1 & -128) == 0 ? (byte) (b1 >> 2) : (byte) (b1 >> 2 ^ 192);
                encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
                encodedData[encodedIndex + 1] = lookUpBase64Alphabet[k << 4];
                encodedData[encodedIndex + 2] = 61;
                encodedData[encodedIndex + 3] = 61;
            } else if (fewerThan24bits == 16L) {
                b1 = binaryData[dataIndex];
                b2 = binaryData[dataIndex + 1];
                l = (byte) (b2 & 15);
                k = (byte) (b1 & 3);
                val1 = (b1 & -128) == 0 ? (byte) (b1 >> 2) : (byte) (b1 >> 2 ^ 192);
                val2 = (b2 & -128) == 0 ? (byte) (b2 >> 4) : (byte) (b2 >> 4 ^ 240);
                encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
                encodedData[encodedIndex + 1] = lookUpBase64Alphabet[val2 | k << 4];
                encodedData[encodedIndex + 2] = lookUpBase64Alphabet[l << 2];
                encodedData[encodedIndex + 3] = 61;
            }

            if (isChunked && chunksSoFar < chunckCount) {
                System.arraycopy(CHUNK_SEPARATOR, 0, encodedData, encodedDataLength - CHUNK_SEPARATOR.length, CHUNK_SEPARATOR.length);
            }

            return encodedData;
        }
    }

//    public static String decodeToString(String base64Encoded) {
//        byte[] encodedBytes = CodecSupport.toBytes(base64Encoded);
//        return decodeToString(encodedBytes);
//    }
//
//    public static String decodeToString(byte[] base64Encoded) {
//        byte[] decoded = decode(base64Encoded);
//        return CodecSupport.toString(decoded);
//    }
//
//    public static byte[] decode(String base64Encoded) {
//        byte[] bytes = CodecSupport.toBytes(base64Encoded);
//        return decode(bytes);
//    }

    public static byte[] decode(byte[] base64Data) {
        base64Data = discardNonBase64(base64Data);
        if (base64Data.length == 0) {
            return new byte[0];
        } else {
            int numberQuadruple = base64Data.length / 4;
            int encodedIndex = 0;
            int i = base64Data.length;

            while (base64Data[i - 1] == 61) {
                --i;
                if (i == 0) {
                    return new byte[0];
                }
            }

            byte[] decodedData = new byte[i - numberQuadruple];

            for (i = 0; i < numberQuadruple; ++i) {
                int dataIndex = i * 4;
                byte marker0 = base64Data[dataIndex + 2];
                byte marker1 = base64Data[dataIndex + 3];
                byte b1 = base64Alphabet[base64Data[dataIndex]];
                byte b2 = base64Alphabet[base64Data[dataIndex + 1]];
                byte b3;
                if (marker0 != 61 && marker1 != 61) {
                    b3 = base64Alphabet[marker0];
                    byte b4 = base64Alphabet[marker1];
                    decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
                    decodedData[encodedIndex + 1] = (byte) ((b2 & 15) << 4 | b3 >> 2 & 15);
                    decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4);
                } else if (marker0 == 61) {
                    decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
                } else {
                    b3 = base64Alphabet[marker0];
                    decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
                    decodedData[encodedIndex + 1] = (byte) ((b2 & 15) << 4 | b3 >> 2 & 15);
                }

                encodedIndex += 3;
            }

            return decodedData;
        }
    }

    static byte[] discardNonBase64(byte[] data) {
        byte[] groomedData = new byte[data.length];
        int bytesCopied = 0;
        byte[] packedData = data;
        int len$ = data.length;

        for (int i$ = 0; i$ < len$; ++i$) {
            byte aByte = packedData[i$];
            if (isBase64(aByte)) {
                groomedData[bytesCopied++] = aByte;
            }
        }

        packedData = new byte[bytesCopied];
        System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
        return packedData;
    }

    static {
        int i;
        for (i = 0; i < 255; ++i) {
            base64Alphabet[i] = -1;
        }

        for (i = 90; i >= 65; --i) {
            base64Alphabet[i] = (byte) (i - 65);
        }

        for (i = 122; i >= 97; --i) {
            base64Alphabet[i] = (byte) (i - 97 + 26);
        }

        for (i = 57; i >= 48; --i) {
            base64Alphabet[i] = (byte) (i - 48 + 52);
        }

        base64Alphabet[43] = 62;
        base64Alphabet[47] = 63;

        for (i = 0; i <= 25; ++i) {
            lookUpBase64Alphabet[i] = (byte) (65 + i);
        }

        i = 26;

        int j;
        for (j = 0; i <= 51; ++j) {
            lookUpBase64Alphabet[i] = (byte) (97 + j);
            ++i;
        }

        i = 52;

        for (j = 0; i <= 61; ++j) {
            lookUpBase64Alphabet[i] = (byte) (48 + j);
            ++i;
        }

        lookUpBase64Alphabet[62] = 43;
        lookUpBase64Alphabet[63] = 47;
    }
}
View Code

 RSA

package com.tensquare.encrypt.rsa;

import sun.misc.BASE64Decoder;
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;
import java.util.HashMap;
import java.util.Map;

public class RSA {
    /** */
    /**
     * 加密算法RSA
     */
    public static final String KEY_ALGORITHM = "RSA";

    /** */
    /**
     * 签名算法
     */
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";

    /** */
    /**
     * 获取公钥的key
     */
    private static final String PUBLIC_KEY = "RSAPublicKey";

    /** */
    /**
     * 获取私钥的key
     */
    private static final String PRIVATE_KEY = "RSAPrivateKey";

    /** */
    /**
     * RSA最大加密明文大小
     */
    //private static final int MAX_ENCRYPT_BLOCK = 117;
    private static final int MAX_ENCRYPT_BLOCK = 245;

    /** */
    /**
     * RSA最大解密密文大小
     */
    //private static final int MAX_DECRYPT_BLOCK = 128;
    private static final int MAX_DECRYPT_BLOCK = 256;

    /** */
    /**
     * <p>
     * 生成密钥对(公钥和私钥)
     * </p>
     *
     * @return
     * @throws Exception
     */
    public static Map<String, Object> genKeyPair() throws Exception {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        keyPairGen.initialize(1024);
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        Map<String, Object> keyMap = new HashMap<String, Object>(2);
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }

    /** */
    /**
     * <p>
     * 用私钥对信息生成数字签名
     * </p>
     *
     * @param data       已加密数据
     * @param privateKey 私钥(BASE64编码)
     * @return
     * @throws Exception
     */
    public static String sign(byte[] data, String privateKey) throws Exception {
        byte[] keyBytes = Base64Utils.decode(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(privateK);
        signature.update(data);
        return Base64Utils.encode(signature.sign());
    }

    /** */
    /**
     * 112.     * <p>
     * 113.     * 校验数字签名
     * 114.     * </p>
     * 115.     *
     * 116.     * @param data 已加密数据
     * 117.     * @param publicKey 公钥(BASE64编码)
     * 118.     * @param sign 数字签名
     * 119.     *
     * 120.     * @return
     * 121.     * @throws Exception
     * 122.     *
     * 123.
     */
    public static boolean verify(byte[] data, String publicKey, String sign)
            throws Exception {
        byte[] keyBytes = Base64Utils.decode(publicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PublicKey publicK = keyFactory.generatePublic(keySpec);
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(publicK);
        signature.update(data);
        return signature.verify(Base64Utils.decode(sign));
    }

    /** */
    /**
     * 137.     * <P>
     * 138.     * 私钥解密
     * 139.     * </p>
     * 140.     *
     * 141.     * @param encryptedData 已加密数据
     * 142.     * @param privateKey 私钥(BASE64编码)
     * 143.     * @return
     * 144.     * @throws Exception
     * 145.
     */
    public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)
            throws Exception {
        // byte[] keyBytes = Base64Utils.decode(privateKey);
        // PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateK = getPrivateKey(privateKey);
        //Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateK);
        
        int inputLen = encryptedData.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段解密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        
        return decryptedData;
    }

    /**
     * 得到私钥
     *
     * @param key 密钥字符串(经过base64编码)
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String key) throws Exception {
        byte[] keyBytes;
        keyBytes = (new BASE64Decoder()).decodeBuffer(key);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }

    /**
     * 得到公钥
     *
     * @param key 密钥字符串(经过base64编码)
     * @throws Exception
     */
    public static PublicKey getPublicKey(String key) throws Exception {
        byte[] keyBytes;
        keyBytes = (new BASE64Decoder()).decodeBuffer(key);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }
    /** */
    /**
     * 176.     * <p>
     * 177.     * 公钥解密
     * 178.     * </p>
     * 179.     *
     * 180.     * @param encryptedData 已加密数据
     * 181.     * @param publicKey 公钥(BASE64编码)
     * 182.     * @return
     * 183.     * @throws Exception
     * 184.
     */
    public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)
            throws Exception {
        byte[] keyBytes = Base64Utils.decode(publicKey);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicK = keyFactory.generatePublic(x509KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, publicK);
        int inputLen = encryptedData.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段解密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return decryptedData;
    }

    /** */
    /**
     * 215.     * <p>
     * 216.     * 公钥加密
     * 217.     * </p>
     * 218.     *
     * 219.     * @param data 源数据
     * 220.     * @param publicKey 公钥(BASE64编码)
     * 221.     * @return
     * 222.     * @throws Exception
     * 223.
     */
    public static byte[] encryptByPublicKey(byte[] data, String publicKey)
            throws Exception {
        // byte[] keyBytes = Base64Utils.decode(publicKey);
        // X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicK = getPublicKey(publicKey);
        // 对数据加密
        //Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicK);
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段加密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return encryptedData;
    }

    /** */
    /**
     * 255.     * <p>
     * 256.     * 私钥加密
     * 257.     * </p>
     * 258.     *
     * 259.     * @param data 源数据
     * 260.     * @param privateKey 私钥(BASE64编码)
     * 261.     * @return
     * 262.     * @throws Exception
     * 263.
     */
    public static byte[] encryptByPrivateKey(byte[] data, String privateKey)
            throws Exception {
        byte[] keyBytes = Base64Utils.decode(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateK);
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段加密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return encryptedData;
    }
    /** */
    /**
     * 294.     * <p>
     * 295.     * 获取私钥
     * 296.     * </p>
     * 297.     *
     * 298.     * @param keyMap 密钥对
     * 299.     * @return
     * 300.     * @throws Exception
     */
//    public static String getPrivateKey(Map<String, Object> keyMap)
//            throws Exception {
//        Key key = (Key) keyMap.get(PRIVATE_KEY);
//        return Base64Utils.encode(key.getEncoded());
//    }

    /** */
    /**
     * 309.     * <p>
     * 310.     * 获取公钥
     * 311.     * </p>
     * 312.     *
     * 313.     * @param keyMap 密钥对
     * 314.     * @return
     * 315.     * @throws Exception
     * 316.
     */
    public static String getPublicKey(Map<String, Object> keyMap)
            throws Exception {
        Key key = (Key) keyMap.get(PUBLIC_KEY);
        return Base64Utils.encode(key.getEncoded());
    }

}
View Code

 RsaKeys

package com.tensquare.encrypt.rsa;

/**
 * rsa加解密用的公钥和私钥
 * @author Administrator
 *
 */
public class RsaKeys {

    //生成秘钥对的方法可以参考这篇帖子
    //https://www.cnblogs.com/yucy/p/8962823.html

    //服务器公钥
    private static final String serverPubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuJ8CmuTbp3iNAtSWTeYa" +
            "DqA8WwqeCNfEnbCPOUYRn3JoqxMUxUF1GoDOFTNoBJl2VQJa6u80ovf9OYiNlwgb" +
            "Gf+h744kF7cY2c2MroS+gbav4Gf6pyy7W4EbxRcqzzqNcrAfFmQGh7uaIRB5KzI7" +
            "PMSk61UT9iNLeBKscn6bNIdbd13S0pXUJrf2yRYtdUYi2ab9uudSOzUSPgXgYAHS" +
            "AeF2dnCW3OPQh1TnBUopu+Cy7ficundydVQgWa4US8U4Hwj4wukt0ZZyLuuFygsr" +
            "7JwC1ejHtCMY27EOKfHpIiW9/EWPWUg6cTJSCZugVHV/QO5TkibhwxDBX4yWArms" +
            "FwIDAQAB";

    //服务器私钥(经过pkcs8格式处理)
    private static final String serverPrvKeyPkcs8 = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC4nwKa5NuneI0C" +
            "1JZN5hoOoDxbCp4I18SdsI85RhGfcmirExTFQXUagM4VM2gEmXZVAlrq7zSi9/05" +
            "iI2XCBsZ/6HvjiQXtxjZzYyuhL6Btq/gZ/qnLLtbgRvFFyrPOo1ysB8WZAaHu5oh" +
            "EHkrMjs8xKTrVRP2I0t4Eqxyfps0h1t3XdLSldQmt/bJFi11RiLZpv2651I7NRI+" +
            "BeBgAdIB4XZ2cJbc49CHVOcFSim74LLt+Jy6d3J1VCBZrhRLxTgfCPjC6S3RlnIu" +
            "64XKCyvsnALV6Me0IxjbsQ4p8ekiJb38RY9ZSDpxMlIJm6BUdX9A7lOSJuHDEMFf" +
            "jJYCuawXAgMBAAECggEAP6A9S5h3wt2e60zMiAg3DrdWVaHxGOcTkazZj0mApUzO" +
            "mba3v8txSjL90vyman9g8qcfIjxSDaAdmwhek6BthqY87swz0CB/5gAa7cI9zYJi" +
            "Vpo/HgIih8SVB3WWgViSiuX7sMHEJl8XHTIKMELde3HhzGDDwl4jkjwNRmAvqQgv" +
            "M1kvFiWcguDIMswIarbTgSytK2TqhG98rQj5lq2iLDedFu5++mWdeU4n0yp0btCH" +
            "IP5nnOkOPv4bjgn0SNokHvHtCQGlT0xQbyWnrE/EY/nettZFbHrCjfpjaM0xtPKl" +
            "p0RIoAVsAyEGdPWNYzIulrCpCyvtWUms9iZfv5K3kQKBgQDdqDUcH1R9CtKUCBM+" +
            "Kml9M35YHpzrsuElJg/CKTox5UFWp8ZOMELwp9/XevCjxybTfS7TY2H2v9t9bY1j" +
            "rzt9ipF2nqEFsEQWiQaKErVAM8RaQedy76codBW0SpQ+z1aHin7c7Hee3uO0x4nt" +
            "8fhbyp5Yn2PgIgmniZ76Qa8mCwKBgQDVOc/Yu9yL/W/hbr5NXCTpvxevyb2md1lJ" +
            "PJ74vwdcWyvizI/I8pP0ZoXYdnF3V8Fx4xziQtU/xY/pQyjBoG6mr999qlaMRU0x" +
            "STNFuwOrhs8mXCNJRBALx8fEMuqpAc80sy06zDpP/LQEW0ESJwKu+rrjziP0lKOP" +
            "FMvsbu3VpQKBgAZh1H2lzUn4aM3IWb19fSIUvHuPDhefQ+pM6UE+7KUJI9N56zTP" +
            "IO5K9x/+MzWUA2MthI6jmut+5LP81ohbQExCFCQlNx+xzpQTh/OrzDo4A1xR73cY" +
            "vWhlx0Y0q4YPdD9c1oBH8r3JTyciY69NO0hxUhPdKwQGFt8TEFfGUmO3AoGAKsl6" +
            "EtTH0fOeYs9VMrLd2WX2O9kwzFnAufiHMgUrVfYZnV5NMBa1Z+K20xQZeshKUi8v" +
            "2ZttrWlYkodeg1RNP/ek0lO/IFC7x7sXpdN8Tgw0P09X6VjWG3cQeCd7fUSWrs2R" +
            "su3OecSM3x7stNbNLA22OQZhoq+9DnYu4Zf0890CgYBgHsYlAHBNkabLGT5GMZg5" +
            "Vk2vSEIECY5KUDl2GzUYy3/yJyKGIwySVNDbSS+8VEFJowFXf9unIFymNU61tJ44" +
            "c9mF2DL+CzGx3LgmHmfyarlXh5adv9Q6fzVjgtYOgxPS+OeZFWgFVnILC6iqUGRs" +
            "NDtB4qh/0XUcjgZGEh3SdQ==";

    public static String getServerPubKey() {
        return serverPubKey;
    }

    public static String getServerPrvKeyPkcs8() {
        return serverPrvKeyPkcs8;
    }
    
}
View Code

 RsaService

package com.tensquare.encrypt.service;

/**
 * 
* @ClassName: RsaService
* @Description: rsa加密解密服务接口
* @author 李建
* @date 2018年6月21日 下午3:27:34
*
 */
public interface RsaService {
    
    /***
     * RSA解密
     *
     * @param encryptData
     * @return
     * @throws Exception
     */
    public String RSADecryptDataPEM(String encryptData, String prvKey) throws Exception;
    
    /***
     * RSA解密
     *
     * @param encryptBytes
     * @return
     * @throws Exception
     */
    public String RSADecryptDataBytes(byte[] encryptBytes, String prvKey) throws Exception;
    
    /***
     * RSA加密
     *
     * @param data
     * @return
     * @throws Exception
     */
    public String RSAEncryptDataPEM(String data, String pubKey) throws Exception;
    
    public String getRsaAlgorithm();
}
View Code

 RsaServiceImpl

package com.tensquare.encrypt.service;

import com.tensquare.encrypt.rsa.Base64Utils;
import com.tensquare.encrypt.rsa.RSA;
import org.springframework.stereotype.Service;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;

/**
 * RSA 加解密
 *
 * @author Administrator
 */
@Service("RsaService")
public class RsaServiceImpl implements RsaService {

    /***
     * RSA解密
     *
     * @param encryptData
     * @return
     * @throws Exception
     */
    public String RSADecryptDataPEM(String encryptData, String prvKey) throws Exception {
        byte[] encryptBytes = encryptData.getBytes();
        byte[] prvdata = RSA.decryptByPrivateKey(Base64Utils.decode(encryptData), prvKey);

        String outString = new String(prvdata, "UTF-8");
        return outString;
    }
    
    @Override
    public String RSADecryptDataBytes(byte[] encryptBytes, String prvKey)
            throws Exception {
        // TODO Auto-generated method stub
        byte[] prvdata = RSA.decryptByPrivateKey(encryptBytes, prvKey);
        String outString = new String(prvdata, "utf-8");
        return outString;
    }

    /***
     * RSA加密
     *
     * @param data
     * @return
     * @throws Exception
     */
    public String RSAEncryptDataPEM(String data, String pubKey) throws Exception {

        byte[] pubdata = RSA.encryptByPublicKey(data.getBytes("UTF-8"), pubKey);
        String outString = new String(Base64Utils.encode(pubdata));

        return outString;
    }

    @Override
    public String getRsaAlgorithm() {
        // TODO Auto-generated method stub
        KeyFactory keyFactory = null;
        try {
            keyFactory = KeyFactory.getInstance("RSA");
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return keyFactory.getAlgorithm();
    }
    
}
View Code

 5. 在src/test/java文件夹下创建测试用例EncryptTest

 该测试用例用于将请求参数加密,代码如下

import com.tensquare.encrypt.EncryptApplication;
import com.tensquare.encrypt.rsa.RsaKeys;
import com.tensquare.encrypt.service.RsaService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = EncryptApplication.class)
public class EncryptTest {

    @Autowired
    private RsaService rsaService;

    @Test
    public void genEncryptDataByPubKey(){
        String data = "{\"title\":\"三十\"}";
        try {
            String encData = rsaService.RSAEncryptDataPEM(data, RsaKeys.getServerPubKey());
            System.out.println("data: "+data);
            System.out.println("encData: "+encData);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

6. 编写filter

 在com.tensquare.encrypt包下新建filters包,然后新建过滤器类RSARequestFilter,添加下面的代码

package com.tensquare.encrypt.filter;

import com.google.common.base.Charsets;
import com.google.common.base.Strings;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.netflix.zuul.http.ServletInputStreamWrapper;
import com.tensquare.encrypt.rsa.RsaKeys;
import com.tensquare.encrypt.service.RsaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

@Component
public class RSARequestFilter extends ZuulFilter {

    @Autowired
    private RsaService rsaService;

    @Override
    public String filterType() {
        //过滤器在什么环境执行,解密操作需要在转发之前执行
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        //设置过滤器的执行顺序
        return FilterConstants.PRE_DECORATION_FILTER_ORDER + 1;
    }

    @Override
    public boolean shouldFilter() {
        //是否使用过滤器,true使用过滤器
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        //过滤器具体执行的逻辑
        System.out.println("过滤器执行了");
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();
//        HttpServletResponse response = currentContext.getResponse();
        try {
            String decryptData = null;
            HashMap dataMap = null;
            String token = null;
            String url = request.getRequestURL().toString();
            InputStream inputStream = currentContext.getRequest().getInputStream();
            String requestParam = StreamUtils.copyToString(inputStream, Charsets.UTF_8);
            if(!Strings.isNullOrEmpty(requestParam)){
                System.out.println(String.format("请求体中的密文:%s",requestParam));
                decryptData = rsaService.RSADecryptDataPEM(requestParam, RsaKeys.getServerPrvKeyPkcs8());
                System.out.println(String.format("解密后的内容:%s",decryptData));
            }
            System.out.println(String.format("request: %s >>> %s,data=%s",request.getMethod(),url,decryptData));
            //把解密后的数据进行转发,需要放到request中
            //postman请求http://127.0.0.1:9013/article/article/search/1/10转发到article微服务
            if(!Strings.isNullOrEmpty(decryptData)){
                System.out.println("json字符串写入request body");
                final byte[] reqBodyBytes = decryptData.getBytes();
                currentContext.setRequest(new HttpServletRequestWrapper(request){
                    @Override
                    public ServletInputStream getInputStream() throws IOException{
                        return new ServletInputStreamWrapper(reqBodyBytes);
                    }

                    @Override
                    public int getContentLength(){
                        return reqBodyBytes.length;
                    }

                    @Override
                    public long getContentLengthLong(){
                        return reqBodyBytes.length;
                    }
                });
            }
            System.out.println("转发request");
            currentContext.addZuulRequestHeader("Content-Type",String.valueOf(MediaType.APPLICATION_JSON)+";charset=UTF-8");
        } catch (Exception e) {
            System.out.println(this.getClass().getName()+"运行出错"+e.getMessage());
        }
        return null;
    }
}

7. 将openssl生成的公钥和私钥添加进RsaKeys中

 openssl生成rsa密钥对方法:https://www.cnblogs.com/ajing2018/p/19304617

 公钥变量:private static final String serverPubKey

 私钥变量:private static final String serverPrvKeyPkcs8

8. 测试请求参数加解密微服务

 启动tensquare_eureka,tensquare_article,tensquare_encrypt,使用EncryptTest类加密请求参数,然后使用postman进行接口调用测试


 

posted on 2025-12-04 04:59  花溪月影  阅读(1)  评论(0)    收藏  举报