前后端通信加密 ,基于Rsa和Aes算法(亲测有效)

请求参数解密
public class DecryptionGlobalFilter implements GlobalFilter, Ordered {

    private final IgnoreUrlsConfig ignoreUrlsConfig;

    public DecryptionGlobalFilter(IgnoreUrlsConfig ignoreUrlsConfig) {
        this.ignoreUrlsConfig = ignoreUrlsConfig;
    }
    /***
     * <p>
     *请求参数解密
     * </p>
     * @author 15382
     * @date 2022/6/30 13:35
     * @param    exchange
     * @param    chain
     * @return reactor.core.publisher.Mono<java.lang.Void>
     */
    @SneakyThrows
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        AntPathMatcher pathMatcher = new AntPathMatcher();
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String path = request.getURI().getPath(); // 当前调用方法的url
        HttpHeaders headers = request.getHeaders();
        log.info("HttpMethod:{},Url:{}", request.getMethod(), request.getURI().getRawPath());
        //  跳过白名单验证,检查白名单(配置)最好把不拦截路径放入配置文件,此处通过正则
        List<String> ignoreUrls = ignoreUrlsConfig.getUrls();
        for (String ignoreUrl : ignoreUrls) {
            if (pathMatcher.match(ignoreUrl, path)) {
                return chain.filter(exchange);
            }
        }
        // 处理参数
        MediaType contentType = headers.getContentType();
        long contentLength = headers.getContentLength();
        if (contentLength > 0) {
            if (MediaType.APPLICATION_JSON.equals(contentType) || MediaType.APPLICATION_JSON_UTF8.equals(contentType)||MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)) {
                return readBody(exchange, chain);
            }
        }
        return chain.filter(exchange);
    }

    private Mono<Void> readBody(ServerWebExchange exchange, GatewayFilterChain chain) {
        //重新构造request,参考ModifyRequestBodyGatewayFilterFactory
        ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());
        MediaType mediaType = exchange.getRequest().getHeaders().getContentType();
        //重点
        Mono<String> modifiedBody = serverRequest.bodyToMono(String.class).flatMap(body -> {
            //因为约定了终端传参的格式,所以只考虑json的情况,如果是表单传参,请自行增加
            if (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || MediaType.APPLICATION_JSON_UTF8.isCompatibleWith(mediaType)||MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(mediaType)) {
                String newBody = null;
                String key = exchange.getRequest().getHeaders().getFirst("key");
                String newKey = RsaUtil.decryptByPrivateKey(key);
                try {
                    // 解密body 此处调用你自己的解密方法
                    newBody = AESUtils.AESdecrypt(body, newKey);
                } catch (Exception e) {
                    e.getMessage();
                }
                    return Mono.just(newBody);
            }
            return Mono.empty();
        });
        BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
        HttpHeaders headers = new HttpHeaders();
        headers.putAll(exchange.getRequest().getHeaders());
        //猜测这个就是之前报400错误的元凶,之前修改了body但是没有重新写content length
        headers.remove("Content-Length");
        //MyCachedBodyOutputMessage 这个类完全就是CachedBodyOutputMessage,只不过CachedBodyOutputMessage不是公共的
        CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
        return bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> {
            ServerHttpRequest decorator = this.decorate(exchange, headers, outputMessage);
            return returnMononew(chain, exchange.mutate().request(decorator).build());
        }));
    }

    ServerHttpRequestDecorator decorate(ServerWebExchange exchange, HttpHeaders headers, CachedBodyOutputMessage outputMessage) {
        return new ServerHttpRequestDecorator(exchange.getRequest()) {
            @Override
            public HttpHeaders getHeaders() {
                long contentLength = headers.getContentLength();
                HttpHeaders httpHeaders = new HttpHeaders();
                httpHeaders.putAll(super.getHeaders());
                if (contentLength > 0L) {
                    httpHeaders.setContentLength(contentLength);
                } else {
                    httpHeaders.set("Transfer-Encoding", "chunked");
                }
                return httpHeaders;
            }

            @Override
            public Flux<DataBuffer> getBody() {
                return outputMessage.getBody();
            }
        };
    }

    private Mono<Void> returnMononew(GatewayFilterChain chain, ServerWebExchange exchange) {
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
        }));
    }

    @Override
    public int getOrder() {
        return 10;
    }
}
返回值统一加密处理
public class EncryptionGlobalFilter implements GlobalFilter, Ordered {

    /***
     * <p>
     *     TODO
     * </p>
     * @author  15382
     * @date    2022/7/4 13:51
     * @param	exchange
     * @param	chain
     * @return  reactor.core.publisher.Mono<java.lang.Void>
    */
    @Override
    @SneakyThrows
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        ServerHttpResponse originalResponse = exchange.getResponse();
        DataBufferFactory bufferFactory = originalResponse.bufferFactory();
        ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                if (body instanceof Flux) {
                    Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;

                    return super.writeWith(fluxBody.buffer().map(dataBuffers -> {

                        DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
                        DataBuffer join = dataBufferFactory.join(dataBuffers);

                        byte[] content = new byte[join.readableByteCount()];

                        join.read(content);
                        // 释放掉内存
                        DataBufferUtils.release(join);
                        // 返回值得字符串
                        String str = new String(content, Charset.forName("UTF-8"));
                        log.info(str);
                        // 加密方法
                        String data = null;
                        try {
                            data = AESUtils.AESencrypt(str, "qwertyuiopasdfgh");
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        String newKey = "qwertyuiopasdfgh";
                      //  String newKey = RsaUtil.encryptByPrivateKey("qwertyuiopasdfgh");
                        originalResponse.getHeaders().setContentLength(data.getBytes().length);
                        originalResponse.getHeaders().set("Key",newKey);
                        return bufferFactory.wrap(data.getBytes());
                    }));
                }
                // if body is not a flux. never got there.
                return super.writeWith(body);
            }
        };
        // replace response with decorator
        return chain.filter(exchange.mutate().response(decoratedResponse).build());
    }

    @Override
    public int getOrder() {
        return -1;
    }

}

AES工具类

public class AESUtils {
    //--------------AES---------------
    private static final String KEY = "qwertyuiopasdfgh";  // 密匙,必须16位
    private static final String ENCODING = "UTF-8"; // 编码
    private static final String ALGORITHM = "AES"; //算法
    private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding"; // 默认的加密算法,ECB模式

    /**
     *  AES加密
     * @param data
     * @return String
     */
    public static String AESencrypt(String data,String key) throws Exception
    {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE,new SecretKeySpec(key.getBytes(),"AES"));
        byte[] b = cipher.doFinal(data.getBytes("utf-8"));
        //采用base64算法进行转码,避免出现中文乱码
        return Base64.encodeBase64String(b);
    }

    /**
     * AES解密
     * @param data
     * @return String
     */
    public static String AESdecrypt(String data,String key) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key.getBytes(), "AES"));
        byte[] b = cipher.doFinal(Base64.decodeBase64(data));
        //采用base64算法进行转码,避免出现中文乱码
        return new String(b);
    }

    public static void main(String[] args) throws Exception {
        System.out.println("key = " + "qwertyuiopasdfgh");
        System.out.println("text = " + "{\"code\":200,\"message\":\"操作成功\",\"data\":{\"token\":\"eyJhbGciOiJSUzI1NiIsInR5cCI6");
        System.out.println("加密为: "+AESUtils.AESencrypt("6fEfqYehC0Xivlh0AxiOcg==", "QJQFf84OE1Qimfq5"));
        System.out.println("解密后: "+AESUtils.AESdecrypt("vWvsbsCpZaCwysmk7yrhCA==", "T8VozM1KGmyA3sjL"));
    }

}

Rsa工具类

public class RsaUtil {
    private static final String KEY_ALGORITHM = "RSA";
    private static final String PK = KeyConstants.publicKey;
    private static final String SK = KeyConstants.privateKey;

    /**
     * 使用RSA公钥加密
     */

    public static String encryptByPublicKey(String str) {
        return Base64.encodeBase64String(getMaxResultEncrypt(str, getPublicKey(Cipher.ENCRYPT_MODE)));
    }
    /**
     * 使用公钥解密
     */
    public static String decryptByPublicKey(String data) {
        try {
            return new String(getMaxResultDecrypt(data, getPublicKey(Cipher.DECRYPT_MODE)));
        }catch (Exception e){
            throw new BusinessException(ErrorCodeEnum.PUBLIC_KEY_DECRYPT);
        }
    }
    /**
     * 使用RSA私钥解密
     *
     * @param str 加密字符串
     */
    public static String decryptByPrivateKey(String str) {
        return new String(getMaxResultDecrypt(str, getPrivateKey(Cipher.DECRYPT_MODE)));
    }

    /**
     * 使用RSA私钥加密
     * @param data       加密数据
     */
    public static String encryptByPrivateKey(String data) {
        try {
            return Base64.encodeBase64String(getMaxResultEncrypt(data, getPrivateKey(Cipher.ENCRYPT_MODE)));
        } catch (Exception e) {
            throw new BusinessException(ErrorCodeEnum.PRIVATE_KEY_ENCRYPT);
        }
    }
    /**
     * 当长度过长的时候,需要分割后加密 117个字节
     */
    private static byte[] getMaxResultEncrypt(String str, Cipher cipher){
        try {
            byte[] inputArray = str.getBytes(StandardCharsets.UTF_8.name());
            int inputLength = inputArray.length;
            // 最大加密字节数,超出最大字节数需要分组加密
            int maxEncryptBlock = 117;
            // 标识
            int offSet = 0;
            byte[] resultBytes = {};
            byte[] cache;
            while (inputLength - offSet > 0) {
                if (inputLength - offSet > maxEncryptBlock) {
                    cache = cipher.doFinal(inputArray, offSet, maxEncryptBlock);
                    offSet += maxEncryptBlock;
                } else {
                    cache = cipher.doFinal(inputArray, offSet, inputLength - offSet);
                    offSet = inputLength;
                }
                resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length);
                System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length);
            }
            return resultBytes;
        }catch (Exception e){
            e.printStackTrace();
            throw new BusinessException(ErrorCodeEnum.ENCRYPT_FAIL);
        }
    }

    /**
     * 当长度过长的时候,需要分割后解密 128个字节
     */
    private static byte[] getMaxResultDecrypt(String str, Cipher cipher) {
        try {
            byte[] inputArray = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8.name()));
            int inputLength = inputArray.length;
            // 最大解密字节数,超出最大字节数需要分组加密
            int maxEncryptBlock = 128;
            int offSet = 0;
            byte[] resultBytes = {};
            byte[] cache;
            while (inputLength - offSet > 0) {
                if (inputLength - offSet > maxEncryptBlock) {
                    cache = cipher.doFinal(inputArray, offSet, maxEncryptBlock);
                    offSet += maxEncryptBlock;
                } else {
                    cache = cipher.doFinal(inputArray, offSet, inputLength - offSet);
                    offSet = inputLength;
                }
                resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length);
                System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length);
            }
            return resultBytes;
        }catch (Exception e){
            e.printStackTrace();
            throw new BusinessException(ErrorCodeEnum.DECRYPT_FAIL);
        }
    }
    /**
     * 根据加解密类型处理公钥
     *
     */
    public static Cipher getPublicKey(int mode) {
        try {
            String publicKey = formatString(PK);
            byte[] decoded = Base64.decodeBase64(publicKey);
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decoded);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            PublicKey key = keyFactory.generatePublic(x509EncodedKeySpec);
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(mode, key);
            return cipher;
        } catch (Exception e) {
            throw new BusinessException(ErrorCodeEnum.PUBLIC_KEY_ERROR);
        }
    }

    /**
     * 根据加解密类型处理私钥
     */
    public static Cipher getPrivateKey(int mode) {
        try {
            //mode 加解密模式 ENCRYPT_MODE = 1  DECRYPT_MODE = 2
            String privateKey = formatString(SK);
            byte[] decoded = Base64.decodeBase64(privateKey);
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(decoded);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            PrivateKey key = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(mode, key);
            return cipher;
        } catch (Exception e) {
            throw new BusinessException(ErrorCodeEnum.PRIVATE_KEY_ERROR);
        }
    }
    public static String formatString(String source) {
        if (source == null) {
            return null;
        }
        return source.replace("\\r", "").replace("\\n", "").trim().replace(" ","");
    }
    public static void main(String[] args) throws Exception {
        String xxStr = "123456";
        //加密
        String bytes1 = RsaUtil.encryptByPrivateKey(xxStr);
        String bytes2 = RsaUtil.encryptByPublicKey(xxStr);
        log.info("公钥加密2:{}",bytes2);
        log.info("私钥加密1:{}",bytes1);

        //解密
        log.info("私钥解密密2:{}",RsaUtil.decryptByPrivateKey(bytes2));
        log.info("公钥解密密1:{}",RsaUtil.decryptByPublicKey(bytes1));

    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值