785834757 1 год назад
Родитель
Сommit
2f237e5e09

+ 34 - 0
authentication/src/main/java/com/jzg/controller/AuthController.java

@@ -1,11 +1,18 @@
 package com.jzg.controller;
 
+import cn.hutool.core.util.HexUtil;
+import cn.hutool.crypto.BCUtil;
+import cn.hutool.crypto.SmUtil;
+import cn.hutool.crypto.asymmetric.SM2;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jzg.commons.annotation.IgnoreTenant;
+import com.jzg.commons.constants.EncryptionConstants;
 import com.jzg.commons.request.RequestSingleParam;
 import com.jzg.commons.util.MinioUtils;
 import com.jzg.commons.util.PasswordUtils;
+import com.jzg.commons.util.sm.Sm2Util;
 import com.jzg.config.JzgTokenService;
 import com.jzg.config.JzgUserDetailsService;
 import com.jzg.config.JzgUsernamePasswordAuthenticationToken;
@@ -33,6 +40,9 @@ import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.tomcat.util.http.fileupload.IOUtils;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
+import org.bouncycastle.util.encoders.Hex;
 import org.redisson.api.RedissonClient;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -46,6 +56,7 @@ import org.springframework.web.context.request.ServletRequestAttributes;
 import javax.imageio.ImageIO;
 import java.awt.image.BufferedImage;
 import java.io.IOException;
+import java.security.*;
 import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.TimeUnit;
@@ -94,7 +105,9 @@ public class AuthController extends BaseController {
             @ApiResponse(responseCode = "200",description = "登录成功"),
             @ApiResponse(responseCode = "403",description = "登录失败")
     })
+
     @PostMapping("/login")
+    @IgnoreTenant
     public void login(@RequestBody LoginFormVo loginFormVo) throws ServletException, IOException {
         HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
         HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
@@ -217,4 +230,25 @@ public class AuthController extends BaseController {
         String userTokenString = getUserTokenString();
         return HttpResult.ok(JSONObject.parseObject(userTokenString,RedisToken.class));
     }
+
+    @Operation(summary = "公钥交换")
+    @PostMapping("/publicKeyExchange")
+    public HttpResult publicKeyExchange(@RequestSingleParam("publicKey") String publicKey) throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException {
+        //redis 存储公钥
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("vueSm2PublicKey",publicKey);
+        //后端生成的SM2私钥
+        SM2 sm2 = SmUtil.sm2();
+        String sm2PrivateKeyHex = HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(sm2.getPrivateKey()));
+        if(sm2PrivateKeyHex.length() > 64){
+            sm2PrivateKeyHex = sm2PrivateKeyHex.substring(2,sm2PrivateKeyHex.length());
+        }
+        String sm2PublicKeyHex = HexUtil.encodeHexStr(((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false));
+        jsonObject.put("javaSm2PrivateKey",sm2PrivateKeyHex);
+        redissonClient.getBucket(EncryptionConstants.SM2_PUBLIC_KEY_REDIS + "admin").set(jsonObject.toJSONString());
+        System.out.printf("SM2公钥:" + sm2PublicKeyHex + "\n");
+        System.out.printf("SM2私钥:" + sm2PrivateKeyHex  + "\n");
+        return HttpResult.ok("success",sm2PublicKeyHex);
+    }
+
 }

+ 1 - 0
authentication/src/main/java/com/jzg/filter/TokenAuthenticationFilter.java

@@ -47,6 +47,7 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
         doList.add("/sendSmsCode");
         doList.add("/appLogin");
         doList.add("/smsCodeLogin");
+        doList.add("/auth/publicKeyExchange");
         String path = request.getRequestURI();
         for (String pattern : doList) {
             // 使用正则表达式匹配  .* 匹配所有以 pattern 开头的路径

+ 11 - 0
commons/src/main/java/com/jzg/commons/constants/EncryptionConstants.java

@@ -0,0 +1,11 @@
+package com.jzg.commons.constants;
+
+import lombok.Data;
+
+@Data
+public class EncryptionConstants {
+
+    public final static String SM2_PUBLIC_KEY_REDIS = "sm2_public_key:";
+
+    public final static String SM4_PRIVATE_KEY_REDIS = "sm4_private_key:";
+}

+ 7 - 0
commons/src/main/java/com/jzg/commons/core/base/BaseController.java

@@ -57,6 +57,13 @@ public class BaseController {
         return userInfo.getString("username");
     }
 
+    public String getUserName(String token){
+        valiedToken(token);
+        String userJsonStr = redissonClient.getBucket(token).get().toString();
+        JSONObject userInfo = JSONObject.parseObject(userJsonStr);
+        return userInfo.getString("username");
+    }
+
     /**
      * 获取用户登录的系统
      * @return

+ 180 - 0
commons/src/main/java/com/jzg/commons/util/sm/Sm2Util.java

@@ -0,0 +1,180 @@
+package com.jzg.commons.util.sm;
+
+import org.bouncycastle.asn1.x9.X9ECParameters;
+import org.bouncycastle.crypto.ec.CustomNamedCurves;
+import org.bouncycastle.crypto.engines.SM2Engine;
+import org.bouncycastle.crypto.params.ECDomainParameters;
+import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import org.bouncycastle.crypto.params.ParametersWithRandom;
+import org.bouncycastle.crypto.signers.SM2Signer;
+import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
+import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
+import org.bouncycastle.jce.ECNamedCurveTable;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.jce.spec.ECParameterSpec;
+import org.bouncycastle.jce.spec.ECPrivateKeySpec;
+import org.bouncycastle.util.encoders.Hex;
+
+import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
+import java.security.*;
+import java.security.spec.ECGenParameterSpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+
+public class Sm2Util {
+    static {
+        // 注册 Bouncy Castle 提供者
+        Security.addProvider(new BouncyCastleProvider());
+    }
+
+    /**
+     * 生成SM2密钥对
+     */
+    public static KeyPair generateSM2KeyPair() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
+        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC");
+        ECGenParameterSpec ecGenParameterSpec = new ECGenParameterSpec("sm2p256v1");
+        keyPairGenerator.initialize(ecGenParameterSpec, new SecureRandom());
+        return keyPairGenerator.generateKeyPair();
+    }
+
+    /**
+     * 公钥加密
+     */
+    public static String encrypt(String data, PublicKey publicKey) throws Exception {
+        SM2Engine engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
+        BCECPublicKey ecPublicKey = (BCECPublicKey) publicKey;
+        ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(ecPublicKey.getQ(), getDomainParameters());
+        engine.init(true, new ParametersWithRandom(publicKeyParameters, new SecureRandom()));
+
+        byte[] encryptedData = engine.processBlock(data.getBytes(StandardCharsets.UTF_8), 0, data.getBytes().length);
+        return Hex.toHexString(encryptedData);
+    }
+
+    /**
+     * 私钥解密
+     */
+    public static String decrypt(String encryptedData, PrivateKey privateKey) throws Exception {
+        SM2Engine engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
+        BCECPrivateKey ecPrivateKey = (BCECPrivateKey) privateKey;
+        ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(ecPrivateKey.getD(), getDomainParameters());
+        engine.init(false, privateKeyParameters);
+
+        byte[] decryptedData = engine.processBlock(Hex.decode(encryptedData), 0, Hex.decode(encryptedData).length);
+
+        return new String(decryptedData, StandardCharsets.UTF_8);
+    }
+
+    // 公钥转换为 HEX 字符串
+    public static PrivateKey convertPKCS8HexToPrivateKey(String hexPrivateKey) throws Exception {
+        byte[] keyBytes = Hex.decode(hexPrivateKey);
+
+        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
+        KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");  // SM2 属于 EC
+        return keyFactory.generatePrivate(keySpec);
+    }
+
+    /**
+     * 私钥签名
+     */
+    public static String sign(String data, PrivateKey privateKey) throws Exception {
+        SM2Signer signer = new SM2Signer();
+        BCECPrivateKey ecPrivateKey = (BCECPrivateKey) privateKey;
+        ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(ecPrivateKey.getD(), getDomainParameters());
+
+        signer.init(true, privateKeyParameters);
+        signer.update(data.getBytes(StandardCharsets.UTF_8), 0, data.getBytes().length);
+        byte[] signature = signer.generateSignature();
+
+        return Hex.toHexString(signature);
+    }
+
+    /**
+     * 公钥验签
+     */
+    public static boolean verify(String data, String signature, PublicKey publicKey) throws Exception {
+        SM2Signer signer = new SM2Signer();
+        BCECPublicKey ecPublicKey = (BCECPublicKey) publicKey;
+        ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(ecPublicKey.getQ(), getDomainParameters());
+
+        signer.init(false, publicKeyParameters);
+        signer.update(data.getBytes(StandardCharsets.UTF_8), 0, data.getBytes().length);
+
+        return signer.verifySignature(Hex.decode(signature));
+    }
+
+    private static ECDomainParameters getDomainParameters() {
+        X9ECParameters ecParameters = CustomNamedCurves.getByName("sm2p256v1");
+        return new ECDomainParameters(ecParameters.getCurve(), ecParameters.getG(), ecParameters.getN());
+    }
+
+    /**
+     * 测试
+     */
+    public static void main(String[] args) throws Exception {
+//        // 生成SM2密钥对
+//        KeyPair keyPair = generateSM2KeyPair();
+//        PublicKey publicKey = keyPair.getPublic();
+//        PrivateKey privateKey = keyPair.getPrivate();
+//
+//        System.out.println("公钥: " + Hex.toHexString(publicKey.getEncoded()));
+//        System.out.println("私钥: " + Hex.toHexString(privateKey.getEncoded()));
+//
+//        // 待加密数据
+//        String data = "Hello, SM2!";
+//        System.out.println("原始数据: " + data);
+//
+//        // 加密 & 解密
+//        String encryptedData = encrypt(data, publicKey);
+//        System.out.println("加密后: " + encryptedData);
+//
+//        PrivateKey privateKey1 = convertPKCS8HexToPrivateKey(Hex.toHexString(privateKey.getEncoded()));
+//
+//        String decryptedData = decrypt(encryptedData, privateKey1);
+//        System.out.println("解密后: " + decryptedData);
+//
+//        // 签名 & 验签
+//        String signature = sign(data, privateKey);
+//        System.out.println("签名: " + signature);
+//
+//        boolean isVerified = verify(data, signature, publicKey);
+//        System.out.println("验签结果: " + isVerified);
+
+        // 添加 BouncyCastle 提供者
+        Security.addProvider(new BouncyCastleProvider());
+
+        // 假设这是你的私钥(需要与公钥配对)
+        String privateKeyHex = "308193020100301306072a8648ce3d020106082a811ccf5501822d047930770201010420c882022305a8e374fdd57d7e49ffb09187e8457a952ada2a25b03aa8834819e0a00a06082a811ccf5501822da14403420004704fb361c034bdf3ef03f8d3e95c797fdcecf34853d86e7ff01631d2a7f57c99d1ced5de038ae593cd176e587099029b3b6dc9f2e985c4e6071aad35604db327"; // 替换为你的私钥
+        BigInteger privateKeyD = new BigInteger(privateKeyHex, 16);
+
+        // 加密数据
+        String encryptedDataHex = "8326f09eaca513fd50b7c57dfb23f65729485e44003e10c7dfb68a6988c1a416314850d01114e48fd89c5d95501c7c835cd2ad4d9ae279eaf231615e25711caf3c70d5b9cb7c5acbe8218893a84e0c0cb1f864397a7f209cee95aad6954307543acd1c515ea20adc4d23a6afbbc9015fb6b8505c2028d54e5c410772205861f7";
+
+        // 获取 SM2 椭圆曲线参数
+        ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("sm2p256v1");
+
+        // 将 ECParameterSpec 转换为 ECDomainParameters
+        ECDomainParameters domainParameters = new ECDomainParameters(
+                ecSpec.getCurve(), // 椭圆曲线
+                ecSpec.getG(),    // 基点 G
+                ecSpec.getN(),     // 阶数 n
+                ecSpec.getH()      // 余因子 h
+        );
+
+        // 创建 ECPrivateKeyParameters
+        ECPrivateKeyParameters privateKey = new ECPrivateKeyParameters(privateKeyD, domainParameters);
+
+        // 解析加密数据
+        byte[] encryptedData = Hex.decode(encryptedDataHex);
+
+        // 初始化 SM2 解密引擎
+        SM2Engine sm2Engine = new SM2Engine();
+        sm2Engine.init(false, privateKey);
+
+        // 解密
+        byte[] decryptedData = sm2Engine.processBlock(encryptedData, 0, encryptedData.length);
+
+        // 输出解密结果
+        System.out.println("Decrypted Data: " + Hex.toHexString(decryptedData));
+    }
+}

+ 173 - 0
commons/src/main/java/com/jzg/commons/util/sm/Sm4Util.java

@@ -0,0 +1,173 @@
+package com.jzg.commons.util.sm;
+
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.engines.SM4Engine;
+import org.bouncycastle.crypto.modes.CBCBlockCipher;
+import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
+import org.bouncycastle.crypto.paddings.ZeroBytePadding;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.crypto.params.ParametersWithIV;
+import org.bouncycastle.util.encoders.Hex;
+
+import java.nio.charset.StandardCharsets;
+import java.security.SecureRandom;
+
+/**
+ * SM4 加解密工具类(支持 ECB 和 CBC)
+ */
+public class Sm4Util {
+
+    private static final int BLOCK_SIZE = 16; // SM4 分组长度
+
+    /**
+     * 生成随机 SM4 密钥
+     * @return 16字节密钥(Hex 编码)
+     */
+    public static String generateKey() {
+        byte[] key = new byte[BLOCK_SIZE];
+        new SecureRandom().nextBytes(key);
+        return Hex.toHexString(key);
+    }
+
+    /**
+     * 生成随机 IV
+     * @return 16字节 IV(Hex 编码)
+     */
+    public static String generateIV() {
+        byte[] iv = new byte[BLOCK_SIZE];
+        new SecureRandom().nextBytes(iv);
+        return Hex.toHexString(iv);
+    }
+
+    /**
+     * SM4-ECB 模式加密
+     * @param keyHex  16字节密钥(Hex 编码)
+     * @param data    明文字符串
+     * @return 加密后的密文(Hex 编码)
+     */
+    public static String encryptECB(String keyHex, String data) {
+        return encrypt(keyHex, null, data, true);
+    }
+
+    /**
+     * SM4-ECB 模式解密
+     * @param keyHex  16字节密钥(Hex 编码)
+     * @param cipherHex 加密后的密文(Hex 编码)
+     * @return 解密后的明文
+     */
+    public static String decryptECB(String keyHex, String cipherHex) {
+        return decrypt(keyHex, null, cipherHex, true);
+    }
+
+    /**
+     * SM4-CBC 模式加密
+     * @param keyHex  16字节密钥(Hex 编码)
+     * @param ivHex   16字节 IV(Hex 编码)
+     * @param data    明文字符串
+     * @return 加密后的密文(Hex 编码)
+     */
+    public static String encryptCBC(String keyHex, String ivHex, String data) {
+        return encrypt(keyHex, ivHex, data, false);
+    }
+
+    /**
+     * SM4-CBC 模式解密
+     * @param keyHex  16字节密钥(Hex 编码)
+     * @param ivHex   16字节 IV(Hex 编码)
+     * @param cipherHex 加密后的密文(Hex 编码)
+     * @return 解密后的明文
+     */
+    public static String decryptCBC(String keyHex, String ivHex, String cipherHex) {
+        return decrypt(keyHex, ivHex, cipherHex, false);
+    }
+
+    /**
+     * SM4 加密(ECB/CBC)
+     */
+    private static String encrypt(String keyHex, String ivHex, String data, boolean isECB) {
+        try {
+            byte[] key = Hex.decode(keyHex);
+            byte[] iv = ivHex != null ? Hex.decode(ivHex) : null;
+            byte[] input = data.getBytes(StandardCharsets.UTF_8);
+
+            PaddedBufferedBlockCipher cipher = createCipher(true, key, iv, isECB);
+            byte[] output = processCipher(cipher, input);
+
+            return Hex.toHexString(output);
+        } catch (Exception e) {
+            throw new RuntimeException("SM4 加密失败", e);
+        }
+    }
+
+    /**
+     * SM4 解密(ECB/CBC)
+     */
+    private static String decrypt(String keyHex, String ivHex, String cipherHex, boolean isECB) {
+        try {
+            byte[] key = Hex.decode(keyHex);
+            byte[] iv = ivHex != null ? Hex.decode(ivHex) : null;
+            byte[] input = Hex.decode(cipherHex);
+
+            PaddedBufferedBlockCipher cipher = createCipher(false, key, iv, isECB);
+            byte[] output = processCipher(cipher, input);
+
+            return new String(output, StandardCharsets.UTF_8).trim();
+        } catch (Exception e) {
+            throw new RuntimeException("SM4 解密失败", e);
+        }
+    }
+
+    /**
+     * 创建 ECB 或 CBC 模式的 Cipher
+     */
+    private static PaddedBufferedBlockCipher createCipher(boolean forEncryption, byte[] key, byte[] iv, boolean isECB) {
+        PaddedBufferedBlockCipher cipher;
+        CipherParameters params;
+
+        if (isECB) {
+            cipher = new PaddedBufferedBlockCipher(new SM4Engine(), new ZeroBytePadding());
+            params = new KeyParameter(key);
+        } else {
+            cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new SM4Engine()), new ZeroBytePadding());
+            params = new ParametersWithIV(new KeyParameter(key), iv);
+        }
+
+        cipher.init(forEncryption, params);
+        return cipher;
+    }
+
+    /**
+     * 处理加密/解密数据
+     */
+    private static byte[] processCipher(PaddedBufferedBlockCipher cipher, byte[] input) throws Exception {
+        byte[] output = new byte[cipher.getOutputSize(input.length)];
+        int len = cipher.processBytes(input, 0, input.length, output, 0);
+        len += cipher.doFinal(output, len);
+        byte[] result = new byte[len];
+        System.arraycopy(output, 0, result, 0, len);
+        return result;
+    }
+
+    public static void main(String[] args) {
+        // 生成密钥和 IV
+        String key = generateKey();
+        String iv = generateIV();
+
+        System.out.println("SM4 密钥: " + key);
+        System.out.println("SM4 IV  : " + iv);
+
+        // 明文
+        String plaintext = "Hello, SM4!";
+        System.out.println("原文: " + plaintext);
+
+        // ECB 加解密
+        String cipherTextECB = encryptECB(key, plaintext);
+        System.out.println("ECB 加密: " + cipherTextECB);
+        System.out.println("ECB 解密: " + decryptECB(key, cipherTextECB));
+
+        // CBC 加解密
+        String cipherTextCBC = encryptCBC(key, iv, plaintext);
+        System.out.println("CBC 加密: " + cipherTextCBC);
+        System.out.println("CBC 解密: " + decryptCBC(key, iv, cipherTextCBC));
+    }
+}

+ 6 - 0
gateway/src/main/java/com/jzg/GateWayApplication.java

@@ -1,9 +1,15 @@
 package com.jzg;
 
+import com.jzg.commons.mapper.OperatorTrajectoryMapper;
+import com.jzg.commons.service.OperatorTrajectoryService;
+import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.FilterType;
 
 @EnableDiscoveryClient
 @SpringBootApplication(exclude ={DataSourceAutoConfiguration.class},scanBasePackages = "com.jzg")

+ 131 - 0
gateway/src/main/java/com/jzg/filter/DecryptFilter.java

@@ -0,0 +1,131 @@
+package com.jzg.filter;
+
+import cn.hutool.core.util.HexUtil;
+import cn.hutool.crypto.ECKeyUtil;
+import cn.hutool.crypto.SmUtil;
+import cn.hutool.crypto.asymmetric.KeyType;
+import cn.hutool.crypto.asymmetric.SM2;
+import com.alibaba.fastjson.JSONObject;
+import com.jzg.commons.constants.EncryptionConstants;
+import com.jzg.commons.core.base.BaseController;
+import com.jzg.commons.util.sm.Sm2Util;
+import com.jzg.commons.util.sm.Sm4Util;
+import org.bouncycastle.crypto.engines.SM2Engine;
+import org.bouncycastle.crypto.signers.PlainDSAEncoding;
+import org.bouncycastle.jcajce.provider.symmetric.SM4;
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.cloud.gateway.filter.factory.rewrite.CachedBodyOutputMessage;
+import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.core.io.buffer.DataBufferFactory;
+import org.springframework.core.io.buffer.DataBufferUtils;
+import org.springframework.core.io.buffer.DefaultDataBufferFactory;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
+import org.springframework.stereotype.Component;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.security.PrivateKey;
+import java.util.concurrent.atomic.AtomicReference;
+
+
+@Component
+public class DecryptFilter implements GlobalFilter {
+    @Value("${isEncrypted}")
+    private boolean isEncrypted;
+
+    @Autowired
+    BaseController baseController;
+
+    @Autowired
+    RedissonClient redissonClient;
+
+    @Override
+    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+        ServerHttpRequest request = exchange.getRequest();
+        boolean contains = request.getURI().getPath().contains("/publicKeyExchange");
+        if(isEncrypted && !contains) {
+            String token = exchange.getRequest().getHeaders().get("authorization").get(0);
+            String userName = baseController.getUserName(token);
+            // 使用 ServerHttpRequestDecorator 包装请求
+            ServerHttpRequestDecorator mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {
+                @Override
+                public Flux<DataBuffer> getBody() {
+                    return super.getBody()
+                            .map(dataBuffer -> {
+                                // 解密逻辑
+                                byte[] decryptedBytes = decrypt(userName,dataBuffer);
+                                return exchange.getResponse().bufferFactory().wrap(decryptedBytes);
+                            });
+                }
+            };
+
+            // 继续过滤器链
+            return chain.filter(exchange.mutate().request(mutatedRequest).build());
+        }else{
+            return chain.filter(exchange);
+        }
+    }
+
+    private byte[] decrypt(String uid,DataBuffer dataBuffer){
+        String data = dataBufferToString(dataBuffer);
+        JSONObject jsonObject = JSONObject.parseObject(data);
+        PrivateKey privateKey = null;
+        String javaSm2PrivateKey = "";
+        String jsonKey = "";
+        for (String key : jsonObject.keySet()) {
+            jsonKey = key;
+            String secretKeyStr = redissonClient.getBucket(EncryptionConstants.SM2_PUBLIC_KEY_REDIS + uid).get().toString();
+            JSONObject secretKey = JSONObject.parseObject(secretKeyStr);
+            javaSm2PrivateKey = secretKey.getString("javaSm2PrivateKey");
+        }
+
+        SM2 sm2 = SmUtil.sm2(javaSm2PrivateKey, null);
+        byte[] decryptedBytes = sm2.decrypt(HexUtil.decodeHex(jsonKey), cn.hutool.crypto.asymmetric.KeyType.PrivateKey);
+        String decryptedSM4Key = new String(decryptedBytes);
+        String orgContext = Sm4Util.decryptECB(decryptedSM4Key, jsonObject.getString(jsonKey));
+        return orgContext.getBytes();
+    }
+
+    // 将字符串转换为 DataBuffer
+    private DataBuffer toDataBuffer(ServerWebExchange exchange, String value) {
+        DataBufferFactory bufferFactory = exchange.getResponse().bufferFactory();
+        return bufferFactory.wrap(value.getBytes(StandardCharsets.UTF_8));
+    }
+
+    public String dataBufferToString(DataBuffer dataBuffer) {
+        ByteBuffer byteBuffer = dataBuffer.asByteBuffer();
+        byte[] bytes = new byte[byteBuffer.remaining()];
+        byteBuffer.get(bytes);
+        String content = new String(bytes, StandardCharsets.UTF_8);
+        DataBufferUtils.release(dataBuffer); // 释放资源
+        return content;
+    }
+
+    public static void main(String[] args) {
+        // **私钥必须是 64 位 HEX**
+        String privateKeyHex = "7e6b4b368a1853ca67a0f806d0d641dfb04134782e8aad5b6f458a6e6ef48a55";
+
+        // **前端传来的密文**
+        String encryptedDataHex = "04ea5b056b1cc5971773be3b1fb4e3bc0a2e445c7b49b0aef5ac124035dbbf78c77984cbf88647301dae90cb80976ce7eed808a6f5b44e9565387aac979ce87689502e1bf3359e8855f08203e8e12c23e489ab83e5cac349429ef2998b2e0ba25e705ef9197d4583c00f017c395c89e0197db2421b7b98934ea1175ef2f48eae0b";
+
+        // **创建 SM2 实例(私钥解密)**
+        SM2 sm2 = SmUtil.sm2(privateKeyHex, null);
+
+        // **解密**
+        byte[] decryptedBytes = sm2.decrypt(HexUtil.decodeHex(encryptedDataHex), cn.hutool.crypto.asymmetric.KeyType.PrivateKey);
+        String decryptedSM4Key = new String(decryptedBytes);
+
+        System.out.println("解密后的 SM4 密钥: " + decryptedSM4Key);
+    }
+}

+ 6 - 1
gateway/src/main/resources/application.yml

@@ -8,5 +8,10 @@ spring:
     allow-bean-definition-overriding: true
   application:
     name: jzg-gateway
+  redis:
+    redisson:
+      address: redis://192.168.0.250:6379
+      password: 123456
+      database: 0
 
-
+isEncrypted: false