bug修改

This commit is contained in:
周鹏 committed 2026-08-24 07:04:50 +08:00
1 parent 79692a8b15
commit 16dec91229
3 files changed
+22 -22

No files matched your search

@@ -19,7 +19,7 @@ import javax.annotation.PostConstruct;
import java.util.List;
/**
* 对白名单接口的 CommonResult.data 做响应加密(需客户端 Header 声明)。
* 对白名单接口的 CommonResult.data 强制做响应加密(不依赖客户端是否声明 X-Resp-Enc)。
*/
@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
@@ -41,7 +41,7 @@ public class RespBodyEncryptResponseAdvice implements ResponseBodyAdvice<Object>
return;
}
support = new RespBodyEncryptSupport(properties.getPrivateKeyBase64(), objectMapper);
log.info("[resp-encrypt] 响应加密已启用,白名单={}", RespBodyEncryptSupport.PATH_SUFFIXES);
log.info("[resp-encrypt] 响应加密已启用(强制),白名单={}", RespBodyEncryptSupport.PATH_SUFFIXES);
}
@Override
@@ -68,13 +68,6 @@ public class RespBodyEncryptResponseAdvice implements ResponseBodyAdvice<Object>
return body;
}
List<String> encHeaders = request.getHeaders().get(RespBodyEncryptSupport.HEADER_RESP_ENC);
String enc = (encHeaders != null && !encHeaders.isEmpty()) ? encHeaders.get(0) : null;
if (!RespBodyEncryptSupport.wantEncrypt(enc)) {
// 旧客户端未声明加密:仍返回明文,便于过渡
return body;
}
List<String> ekHeaders = request.getHeaders().get(RespBodyEncryptSupport.HEADER_RESP_EK);
String ek = (ekHeaders != null && !ekHeaders.isEmpty()) ? ekHeaders.get(0) : null;
try {
@@ -21,7 +21,8 @@ import java.util.Map;
import java.util.Set;
/**
* 响应体加密:客户端用 RSA 公钥加密随机 AES Key(Header),服务端 AES-GCM 加密 data。
* 响应体加密:客户端可用 RSA 公钥加密随机 AES Key(请求 Header),服务端 AES-GCM 加密 data。
* 若客户端未带 Key,服务端生成 AES Key 并写入响应信封字段 {@code ek}(RSA 私钥加密,客户端公钥解密)。
*/
@Slf4j
public class RespBodyEncryptSupport {
@@ -32,7 +33,8 @@ public class RespBodyEncryptSupport {
public static final Set<String> PATH_SUFFIXES = new HashSet<>(Arrays.asList(
"/member/recent/quick-page",
"/member/recent/getById",
"/member/recent/look-wechat"
"/member/recent/look-wechat",
"/member/user/page"
));
private static final String RSA_TRANSFORMATION = "RSA/ECB/PKCS1Padding";
@@ -68,18 +70,14 @@ public class RespBodyEncryptSupport {
return false;
}
public static boolean wantEncrypt(String encHeader) {
return "1".equals(encHeader) || "true".equalsIgnoreCase(encHeader);
}
/**
* 用 Header 中的 RSA 密文解出 AES Key,再加密 data 为信封 Map。
* 白名单接口强制加密 data。优先使用请求头中的 AES Key;否则服务端生成 Key 并写入信封 {@code ek}。
*/
public Map<String, Object> encryptData(Object data, String ekBase64) throws Exception {
if (StrUtil.isBlank(ekBase64)) {
throw new IllegalArgumentException("缺少 X-Resp-Ek");
}
byte[] aesKey = decryptAesKey(ekBase64);
public Map<String, Object> encryptData(Object data, String requestEkBase64) throws Exception {
final boolean serverGeneratedKey = StrUtil.isBlank(requestEkBase64);
final byte[] aesKey = serverGeneratedKey
? generateAesKeyBytes()
: decryptAesKey(requestEkBase64);
byte[] plain = objectMapper.writeValueAsBytes(data == null ? new HashMap<>() : data);
byte[] iv = new byte[IV_LEN];
@@ -95,9 +93,18 @@ public class RespBodyEncryptSupport {
envelope.put("alg", "RSA-PKCS1-AES-256-GCM");
envelope.put("iv", Base64.encode(iv));
envelope.put("ct", Base64.encode(ct));
if (serverGeneratedKey) {
envelope.put("ek", encryptAesKeyForClient(aesKey));
}
return envelope;
}
private String encryptAesKeyForClient(byte[] aesKey) throws Exception {
Cipher rsa = Cipher.getInstance(RSA_TRANSFORMATION);
rsa.init(Cipher.ENCRYPT_MODE, privateKey);
return Base64.encode(rsa.doFinal(aesKey));
}
private byte[] decryptAesKey(String ekBase64) throws Exception {
Cipher rsa = Cipher.getInstance(RSA_TRANSFORMATION);
rsa.init(Cipher.DECRYPT_MODE, privateKey);
@@ -237,7 +237,7 @@ yudao:
base-package: cn.iocoder.yudao
member:
resp-encrypt:
# 默认关;local/prod 配置私钥后开启。客户端带 X-Resp-Enc/X-Resp-Ek 时加密 3 个敏感接口 data
# local/prod 配置私钥后开启。白名单接口 data 强制加密(客户端可带 X-Resp-Ek,也可由响应信封 ek 字段解密)
enabled: true
private-key-base64: ${YUDAO_RESP_ENCRYPT_PRIVATE_KEY:}
web: