Browse Source

接口平台校验

dev-V1.0.7
vincent 1 month ago
parent
commit
5d9139dfde
  1. 26
      script/sql/zfjd-refactoring-v1/其他/gh/ghV1.0.6-0921.sql
  2. 52
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/ApiSignUtil.java
  3. 31
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/handler/ApiSignInterceptor.java
  4. 12
      zdxt-web-server/zdxt-admin-web-server/src/main/resources/application.yml

26
script/sql/zfjd-refactoring-v1/其他/gh/ghV1.0.6-0921.sql

@ -0,0 +1,26 @@
DROP TABLE IF EXISTS sys_api_platform_config;
CREATE TABLE `sys_api_platform_config` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`channel_name` varchar(100) COLLATE utf8mb4_general_ci NOT NULL COMMENT '渠道名称',
`channel_no` varchar(16) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '渠道编号(shiju=市局,longgang=龙岗,longhua=龙华,CIM=CIM大屏)',
`app_key` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '应用Key',
`app_secret` varchar(256) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '应用密钥(HMAC模式)',
`platform_public_key` text COLLATE utf8mb4_general_ci COMMENT '平台公钥(RSA)',
`platform_private_key` text COLLATE utf8mb4_general_ci COMMENT '平台私钥(RSA)',
`caller_public_key` text COLLATE utf8mb4_general_ci COMMENT '调用方公钥(RSA)',
`sign_enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否启用签名验证',
`encrypt_enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否启用加解密',
`ip_whitelist_enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否启用IP白名单(0否 1是)',
`ip_whitelist` varchar(500) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'IP白名单,多个用逗号分隔,为空则不限制',
`status` char(1) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '状态(0正常 1停用)',
`remark` varchar(500) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注',
`create_dept` bigint DEFAULT NULL COMMENT '创建部门',
`create_by` bigint DEFAULT NULL COMMENT '创建者',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` bigint DEFAULT NULL COMMENT '更新者',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_app_key` (`app_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='接口平台配置表';

52
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/ApiSignUtil.java

@ -101,29 +101,37 @@ public class ApiSignUtil {
String platformPublicKey = platformRsa.getPublicKeyBase64(); String platformPublicKey = platformRsa.getPublicKeyBase64();
String platformPrivateKey = platformRsa.getPrivateKeyBase64(); String platformPrivateKey = platformRsa.getPrivateKeyBase64();
System.out.println("app_platformPublicKeykey: " + platformPublicKey); RSA callerRsa = SecureUtil.rsa();
String callerPublicKey = callerRsa.getPublicKeyBase64();
String callerPrivateKey = callerRsa.getPrivateKeyBase64();
System.out.println("=== 平台密钥 ===");
System.out.println("platformPublicKey: " + platformPublicKey);
System.out.println("platformPrivateKey: " + platformPrivateKey); System.out.println("platformPrivateKey: " + platformPrivateKey);
// System.out.println();
// RSA callerRsa = SecureUtil.rsa();
// String callerPublicKey = callerRsa.getPublicKeyBase64(); String sql = "INSERT INTO sys_api_platform_config " +
// "(channel_name, channel_no, app_key, app_secret, " +
// String sql = "INSERT INTO sys_api_platform_config " + "platform_public_key, platform_private_key, caller_public_key, " +
// "(channel_name, channel_no, app_key, app_secret, " + "sign_enabled, encrypt_enabled, ip_whitelist_enabled, ip_whitelist, " +
// "platform_public_key, platform_private_key, caller_public_key, " + "status, create_time) VALUES (\n" +
// "sign_enabled, encrypt_enabled, status, create_time) VALUES (\n" + " 'CIM大屏', 'CIM', '" + appKey + "', '" + appSecret + "',\n" +
// " '龙岗', 'longgang', '" + appKey + "', '" + appSecret + "',\n" + " '" + platformPublicKey + "',\n" +
// " '" + platformPublicKey + "',\n" + " '" + platformPrivateKey + "',\n" +
// " '" + platformPrivateKey + "',\n" + " '" + callerPublicKey + "',\n" +
// " '" + callerPublicKey + "',\n" + " 1, 0, 0, NULL,\n" +
// " 1, 0, '0', NOW()\n" + " '0', NOW()\n" +
// ");"; ");";
//
// System.out.println(sql); System.out.println(sql);
// System.out.println(); System.out.println();
// System.out.println("=== 密钥信息(交给调用方) ==="); System.out.println("=== 密钥信息(交给调用方) ===");
// System.out.println("app_key: " + appKey); System.out.println("app_key: " + appKey);
// System.out.println("app_secret: " + appSecret + " (HMAC签名用)"); System.out.println("app_secret: " + appSecret + " (HMAC签名用)");
// System.out.println("platformPublicKey: " + platformPublicKey + " (加密请求用)"); System.out.println("platformPublicKey: " + platformPublicKey + " (加密请求用)");
System.out.println();
System.out.println("=== 调用方密钥(自行保管,勿泄露) ===");
System.out.println("callerPrivateKey: " + callerPrivateKey + " (解密响应用)");
} }

31
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/handler/ApiSignInterceptor.java

@ -11,11 +11,14 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.HttpStatus; import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.ServletUtils;
import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.redis.utils.RedisUtils;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.HandlerInterceptor;
import java.io.IOException; import java.io.IOException;
import java.time.Duration;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -48,7 +51,7 @@ public class ApiSignInterceptor implements HandlerInterceptor {
return false; return false;
} }
SysApiPlatformConfigEntity consumer = sysApiPlatformConfigService.findByAppKey(appKey).orElse(null); SysApiPlatformConfigEntity consumer = sysApiPlatformConfigService.findByAppKeyFromDb(appKey).orElse(null);
if (consumer == null) { if (consumer == null) {
writeError(response, "无效的 appKey"); writeError(response, "无效的 appKey");
@ -104,7 +107,33 @@ public class ApiSignInterceptor implements HandlerInterceptor {
return false; return false;
} }
// IP 白名单校验
if (Boolean.TRUE.equals(consumer.getIpWhitelistEnabled())) {
String ipWhitelist = consumer.getIpWhitelist();
if (StrUtil.isNotBlank(ipWhitelist)) {
String clientIp = ServletUtils.getClientIP(request);
boolean ipAllowed = StrUtil.split(ipWhitelist, ',')
.stream()
.map(String::trim)
.anyMatch(ip -> ip.equals(clientIp));
if (!ipAllowed) {
writeError(response, "IP 不在白名单中: " + clientIp);
return false;
}
}
}
log.info("API签名验证通过, appKey={}, path={}", appKey, request.getRequestURI()); log.info("API签名验证通过, appKey={}, path={}", appKey, request.getRequestURI());
// // Nonce 唯一性校验(防重放,有效期与 timestamp 超时一致)
// String nonceKey = "api_nonce:" + appKey + ":" + nonce;
// if (Boolean.TRUE.equals(RedisUtils.hasKey(nonceKey))) {
// writeError(response, "nonce 重复");
// return false;
// }
// RedisUtils.setCacheObject(nonceKey, "1",
// Duration.ofSeconds(apiPlatformConfig.getTimestampExpireSeconds()));
return true; return true;
} }

12
zdxt-web-server/zdxt-admin-web-server/src/main/resources/application.yml

@ -340,15 +340,3 @@ http:
api-platform: api-platform:
enabled: true enabled: true
timestamp-expire-seconds: 36000 timestamp-expire-seconds: 36000
consumers:
partner-a:
app-key: ak_partner_a_xxxx
app-secret: sk_partner_a_xxxx
platform-public-key: MIGfMA0GCSq...
platform-private-key: MIICdQIBADANBg...
caller-public-key: MIGfMA0GCSq...
sign-enabled: true
encrypt-enabled: true
allowed-paths:
- /api/v1/data/**
- /api/v1/query/**

Loading…
Cancel
Save