数据中台
接口安全
认证
通讯安全
规则执行
通用组件
通知器
标准化字段校验
定时器
HTTP调用
Rabbit消息发布
脚本可用JAVA库
【必读】上下文
本文档使用 MrDoc 发布
-
+
首页
通讯安全
## 一、通讯安全概述 数据中台提供基于客户端模式的接口通讯加密能力,支持以下安全机制: - **多算法支持**:AES/RSA/无加密三种模式可配置 - **身份认证**:通过客户端ID绑定身份信息 - **请求时效性**:5秒内请求有效(可配置) - **防重放攻击**:通过时间戳+签名双重校验 - **IP白名单**:限制访问来源IP地址 --- ## 二、加密算法说明 | 算法类型 | 密钥要求 | 安全特性 | 适用场景 | |----------|----------|----------|----------| | **AES** | 256位 | 对称加密,速度快 | 常规加密场景 | | **RSA** | 2048位 | 非对称加密,安全性高 | 敏感数据传输 | | **NONE** | 无需密钥 | 无需签名校验 | 对性能要求极高,且数据本身不敏感 | [【附件】WwbcpCryptoKit.java](/media/attachment/2025/07/WwbcpCryptoKit.java) --- ## 三、通讯安全接口规范 ### 1. 请求头要求 | Header字段 | 必填 | 说明 | |------------|------|------| | X-Request-Time | 是 | 请求时间戳(毫秒级),用于防重放攻击 | | X-Sign | 是 | 请求签名,用于验证请求的完整性和真实性(算法见下文) | | Content-Type | 是 | 内容类型,加密请求为`application/octet-stream`,无加密为`application/json` | | Authorization | 是 | 参考`认证`获取access_token | ### 2. 参数格式 - GET请求:URL参数需按key升序排列 - POST请求:body需为JSON格式 ### 3. 响应格式 - 加密模式:响应体为加密后的二进制数据,Content-Type为`application/octet-stream` - 无加密模式:响应体为标准JSON格式,Content-Type为`application/json` ### 4. 响应体结构 ```json { "code": 0, // 状态码,0表示成功,其他表示失败 "msg": "操作成功", // 响应消息 "data": {} // 响应数据,可能为对象、数组或null } ``` --- ## 四、签名验证流程 签名是确保请求完整性和防止请求被篡改的重要机制。签名生成和验证流程如下: ``` +-------------------+ +-------------------+ +-------------------+ | 1. 准备签名材料 |---->| 2. 生成签名字符串 |---->| 3. 服务端验证 | +-------------------+ +-------------------+ +-------------------+ ``` 1. **准备签名材料** - 获取所有查询参数 `参考 WwbcpCryptoKit.getSortedQueryParameters()方法` - 提取请求体内容 2. **生成签名字符串** - AES:`aes.sign()` - RSA:`rsa.sign()` - NONE: `无需签名` ```java // 根据query参数、请求体、时间戳和clientId生成加密字符串 String signStr = getSignStr(queryParameters, reqBody, requestTime, clientId); ``` 3. **服务端验证** 服务端接收到请求后,会对签名解密提取签名中的请求时间戳,并与请求头中的`X-Request-Time`进行比对,验证请求的完整性和真实性。 - 时间戳有效期(默认5000ms) - 签名匹配验证 --- ## 五、接口调用流程 完整的接口调用流程如下: ``` 客户端 服务端 | | |--- 1. 准备请求参数 ---------------------------> | | | |--- 2. 生成请求时间戳 -------------------------> | | | |--- 3. 计算请求签名 ---------------------------> | | | |--- 4. 加密请求体 -----------------------------> | | | |--- 5. 设置请求头 -----------------------------> | | | |--- 6. 发送HTTP请求 ---------------------------> | | | | 7. 验证客户端 ---| | | | 8. 验证签名 -----| | | | 9. 解密请求体 ---| | | | 10. 处理业务逻辑 --| | | | 11. 加密响应体 ---| | | |<-- 12. 返回加密响应 ---------------------------- | | | |--- 13. 解密响应体 ---------------------------> | | | |--- 14. 处理响应结果 --------------------------> | | | ``` ## 六、错误处理机制 通讯安全机制定义了统一的错误处理流程,确保客户端能够正确识别和处理各类错误。 ### 1. 错误响应格式 所有错误响应都遵循统一的JSON格式: ``` { "code": 400, // 错误状态码 "msg": "错误描述信息" // 错误详细说明 } ``` ### 2. 常见错误码 | 错误码 | 说明 | 处理建议 | |------------|------|------| | 400 | 请求参数错误 | 检查客户端ID和签名、检查IP白名单配置 | | 500 | 服务器内部错误 | 联系系统管理员 | ## 七、通讯安全接口配置 ### 配置项说明 |配置项|示例值| |----|----| | 客户端唯一标识 |test_client | 客户端名称 |测试客户端 | 加密算法(AES/RSA/NONE) |AES | 通信密钥(AES密钥或RSA公钥) |8NONwyJtHesysWpM | RSA私钥(仅RSA算法需要) |MIIEvAIBADANBgkq... | 最大时间差(毫秒) |5000 | IP白名单(逗号分隔) |192.168.1.1,192.168.1.2 | 执行结果通知地址 |http://example.com/notify | 管理员用户名(将客户端与用户关联) |test_123 ## 八、接口安全特性 ### 1. 数据机密性 通过AES或RSA加密算法,确保传输数据不被未授权方获取和理解。 ### 2. 数据完整性 通过签名机制,确保数据在传输过程中不被篡改,任何修改都会导致签名验证失败。 ### 3. 身份认证 通过客户端ID和签名验证,确保请求来自合法的客户端。 ### 4. 请求防重放 通过时间戳和最大时间差机制,防止请求被重放。 ### 5. 访问控制 通过IP白名单机制,限制只有特定IP地址的客户端才能访问接口。 ## 九、接口安全调用示例 ### 1. Java客户端调用示例(AES加密) ```java import cn.hutool.core.net.url.UrlBuilder; import cn.hutool.http.ContentType; import cn.hutool.http.Header; import cn.hutool.http.HttpRequest; import cn.hutool.json.JSONUtil; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.List; import java.util.Map; public class AesApiClientExample { private static final String API_URL = "http://172.16.10.5:49999/dataflow/scene/exec"; private static final String AUTHORIZATION = "Bearer c9e6a56e-b67e-44da-820c-aaee703ab550"; private static final String CLIENT_ID = "test"; private static final String AES_KEY = "w4MMcMdPzaKbC9FA"; public static void main(String[] args) { // 1. 准备请求参数 Map<String, Object> params = new HashMap<>(); params.put("name", "测试数据"); params.put("value", 100); String jsonBody = JSONUtil.toJsonStr(params); // 2. 生成请求时间戳 String requestTime = String.valueOf(System.currentTimeMillis()); // 3. 创建加密策略 WwbcpCryptoKit.CryptoStrategy strategy = WwbcpCryptoKit.create("AES", AES_KEY, null, null); // 4. 获取请求URL中的查询参数 Map<String, List<String>> queryParameters = new HashMap<>(); String sceneCode = "shareChainTest"; queryParameters.put("sceneCode", List.of(sceneCode)); // 5. 生成签名 String sign = strategy.sign(queryParameters, jsonBody, requestTime, CLIENT_ID); // 6. 加密请求体 byte[] encryptedBody = strategy.encrypt(jsonBody.getBytes(StandardCharsets.UTF_8)); // 7. 发送请求 String url = UrlBuilder.of(API_URL).addQuery("sceneCode", sceneCode).build(); byte[] responseBytes = HttpRequest.post(url) .header(Header.AUTHORIZATION.getValue(), AUTHORIZATION) .header("X-Request-Time", requestTime) .header("X-Sign", sign) .header(Header.CONTENT_TYPE.getValue(), ContentType.OCTET_STREAM.getValue()) .body(encryptedBody) .execute() .bodyBytes(); // 8. 解密响应 byte[] decryptedResponse = strategy.decrypt(responseBytes); String responseJson = new String(decryptedResponse, StandardCharsets.UTF_8); System.out.println("响应结果: \n" + JSONUtil.toJsonPrettyStr(responseJson)); } } ``` ### 2. Java客户端调用示例(RSA加密) ```java import cn.hutool.core.net.url.UrlBuilder; import cn.hutool.http.ContentType; import cn.hutool.http.Header; import cn.hutool.http.HttpRequest; import cn.hutool.json.JSONUtil; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.List; import java.util.Map; public class RsaApiClientExample { private static final String API_URL = "http://172.16.10.5:49999/dataflow/scene/exec"; private static final String AUTHORIZATION = "Bearer 89908292-58c2-46e5-9431-ba0cad1ed12b"; private static final String CLIENT_ID = "test"; // 中台公钥 private static final String WWBCP_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDeoNUJPPOgXnMBZpr8njXSalYFjxNCaUsOrkUtjM8CtviRw7zgKDuVZ8KpMGRwyUwFTxsh5keUIM97SYX+weT0id7pIS4pu3QBkxY7XBgjE3bSvPTTT702UZZaLW8IU5EfD0CwFVuBwP2986g0yoNBhPf5C5DbzNT+L54vvrl0nQIDAQAB"; // 业务系统私钥 private static final String PRIVATE_KEY = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKlcL/OJzq6GyKFWqadmn2xyNfShtwfO+9Aa5eGSsSScx90Z6294tvekowuhqwsEOvDxlySmYXe+TpztgfeG6UIheY4QIuqimTv4+lgo7rrcjOce4ff3rJnFBXynkC41bxfRPe/KXGVAREZJ+0ExE78On95iJL6UU2CR/7JbW+SPAgMBAAECgYAz5vUpESgek17kFu+KRmiALyY68N5rTbMdTUj7Dt4r5sJXj6x37opALZvsIiENkL/RfHCCAl1neZKVBDKq3ZUZNzA2gIOQw3bQns7QE96ISVxgeETnjW8QDPS5KUhmK2yL6kxxLRD+5WAxGGd4K7N74Ru0212INBh8ld5pGYeUNQJBAOouc776Sy3AGnXRXVix0bWJVL40Vo7Rf5Bq8j0Ir/wwOqQoJckdjxKp+U6xV2k5mxApnYOUpBpL4CnV+diLHTMCQQC5I6hMwqm0NvKmShBW38QrulqMM5nl1jVCSh+uCDeOCv08Ee1k+bo9fv4RqEqFkfbqg1tcgKxfsyBL4Rs5a8M1AkEAgk9e8QJuGwMutijOfLBWNWI52a1eDRLenQolyXiwFPDxcK82d3cPSh9zLyrXrSH0+0Vs9O8dcdSO5DjBUpH2qQJBAJ6zVCdIjpQurd2hi1QMyGn7enbIHNoJvumuBG34GTcncF+3tlliQCVK4JteOVM6BgCMzRoEKr52G+8vbVjRaSkCQApm6ppEq8ZOd2vDx1zgJpDcVpYUWwf919nB4IUN4zq9rUnGugSciyX75iin8Xj8BSBU0GFzG0NqNvUJTkwxPhk="; public static void main(String[] args) { // 1. 准备请求参数 Map<String, Object> params = new HashMap<>(); params.put("name", "测试数据"); params.put("value", 100); String jsonBody = JSONUtil.toJsonStr(params); // 2. 生成请求时间戳 String requestTime = String.valueOf(System.currentTimeMillis()); // 3. 创建加密策略 WwbcpCryptoKit.CryptoStrategy encryptStrategy = WwbcpCryptoKit.create("RSA", null, WWBCP_PUBLIC_KEY, null); // 4. 获取请求URL中的查询参数 Map<String, List<String>> queryParameters = new HashMap<>(); String sceneCode = "shareChainTest"; queryParameters.put("sceneCode", List.of(sceneCode)); // 5. 生成签名 String sign = encryptStrategy.sign(queryParameters, jsonBody, requestTime, CLIENT_ID); // 6. 加密请求体 byte[] encryptedBody = encryptStrategy.encrypt(jsonBody.getBytes(StandardCharsets.UTF_8)); // 7. 发送请求 String url = UrlBuilder.of(API_URL).addQuery("sceneCode", sceneCode).build(); byte[] responseBytes = HttpRequest.post(url) .header(Header.AUTHORIZATION.getValue(), AUTHORIZATION) .header("X-Request-Time", requestTime) .header("X-Sign", sign) .header(Header.CONTENT_TYPE.getValue(), ContentType.OCTET_STREAM.getValue()) .body(encryptedBody) .execute() .bodyBytes(); // 8. 创建解密策略,解密响应 WwbcpCryptoKit.CryptoStrategy decryptStrategy = WwbcpCryptoKit.create("RSA", null, null, PRIVATE_KEY); byte[] decryptedResponse = decryptStrategy.decrypt(responseBytes); String responseJson = new String(decryptedResponse, StandardCharsets.UTF_8); System.out.println("响应结果: \n" + JSONUtil.toJsonPrettyStr(responseJson)); } } ```
admin
2025年12月22日 15:25
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码