bug修改
This commit is contained in:
1 parent
79692a8b15
commit
16dec91229
3 files changed
+22
-22
No files matched your search
+2
-9
@@ -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 {
|
||||
|
||||
+19
-12
@@ -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:
|
||||
|
||||
Reference in new issue
Block a user