当前位置:网站首页>三方对接接口数据安全问题
三方对接接口数据安全问题
2022-08-02 14:14:00 【zhangyu丶】
文档说明
小记一下在与第三方对接过程的一些操作
对接流程

数据传输
每次请求均会对请求来源以及数据的合法性进行校验,采取以下策略,之后接口明细中会说明采用哪种加密方式
获取 Token
请求地址:
POST https:xxxx
接口说明:获取调用凭据,有效期 24h、获取后之后调用接口添加到请求头Authorization中
| 请求参数 | ||||
|---|---|---|---|---|
| 字段 | 数据类型 | 是否必传 | 说明 | 示例 |
| app_id | String | 是 | 客户端ID | thirdpartner |
| app_secret | String | 是 | 客户端密钥 | @m2!2q15^#0d&@ |
| 响应参数 | ||
|---|---|---|
| 字段 | 说明 | 示例 |
| code | 响应状态码 | 200 |
| msg | 响应描述信息 | 请求成功 |
| data | 响应体 | eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQ… |
常规数据加密
常规数据加密,每次请求数据添加随机字符串
once_str和时间戳timestamp并通过 MD5 对全部数据进行加密、接收方对其进行校验证,示例如下
public class EncryptSign {
public static final String APP_ID = "thirdpartner";
public static final String APP_SECRET = "@m*2!2q1*5^#0d&@";
// 生成签名
public static String createSign(SortedMap<String, String> params) {
return params.keySet().stream()
.sorted()
.map(k -> k + "=" + params.get(k) + "&")
.reduce((x, y) -> x + y)
.map(d -> d.substring(0, d.length() - 1))
.map(d -> d.concat(APP_SECRET))
.map(EncryptSign::encode)
.map(String::toUpperCase)
.get();
}
public static boolean verifySign(HttpServletRequest request) {
Map<String, String[]> params = request.getParameterMap();
SortedMap<String, String> map = new TreeMap<>();
String expSign = null;
for (Map.Entry<String, String[]> pv : params.entrySet()) {
String param = pv.getKey();
String[] value = pv.getValue();
if (!param.equals("sign")) {
map.put(param, value[0]);
} else {
expSign = value[0];
}
}
return expSign.equals(createSign(map));
}
public static String generateOnceStr() {
return UUID.randomUUID().toString().replaceAll("-", "");
}
public static String encode(String value) {
StringBuilder sb = new StringBuilder();
try {
MessageDigest md = MessageDigest.getInstance(MD5);
byte[] bs = value.getBytes();
byte[] mb = md.digest(bs);
for (int i = 0; i < mb.length; i++) {
int v = mb[i] & 0xFF;
if (v < 16) {
sb.append("0");
}
sb.append(Integer.toHexString(v));
}
} catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}
public static void main(String[] args) {
//创建随机字符串和时间戳
String once_str = generateOnceStr();
String timestamp = String.valueOf(System.currentTimeMillis());
//测试数据集
SortedMap<String, String> params = new TreeMap<>();
params.put("param1", "a");
params.put("param2", "b");
params.put("once_str", once_str);
params.put("timestamp", timestamp);
//常规数据加密
params.put("sign", createSign(params));
System.out.println(params);
}
}
调用示例
Map<String, String> map = new HashMap<>();
// 业务参数
map.put("app_id", "xxxx");
map.put("app_secret", "xxxx");
// 公共参数
map.put("once_str", EncryptSign.generateOnceStr());
map.put("timestamp", String.valueOf(System.currentTimeMillis()));
// MD5 加密
map.put("sign", EncryptSign.createSign(map));
// Http 调用
String url = "http://xxx/xx/xx";
String result = HttpClientUtil.httpPost(url, map);
System.out.println(result);
敏感数据加密
涉及敏感数据,采用 AES 进行加解密,注意妥善保管密钥,示例如下
public class EncryptAES {
private static final String secret = "@5^22&%c*9^283*@";
private static final String algorithm = "AES/ECB/PKCS5Padding";
//加密
public static String encrypt(String content) {
try {
Security.addProvider(new SunJCE());
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(ENCRYPT_MODE, new SecretKeySpec(secret.getBytes(), AES));
return Base64.getEncoder().encodeToString(cipher.doFinal(content.getBytes("UTF-8")));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//解密
public static String decrypt(String encrypt) {
try {
Security.addProvider(new SunJCE());
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(DECRYPT_MODE, new SecretKeySpec(secret.getBytes("UTF-8"), AES));
return new String(cipher.doFinal(Base64.getDecoder().decode(encrypt)));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
//创建随机字符串和时间戳
String once_str = EncryptSign.generateOnceStr();
String timestamp = String.valueOf(System.currentTimeMillis());
//测试数据集
SortedMap<String, String> params = new TreeMap<>();
params.put("param1", "a");
params.put("param2", "b");
params.put("once_str", once_str);
params.put("timestamp", timestamp);
String content = JSON.toJSONString(params);
System.out.println("明文: " + content);
System.out.println("加密: " + encrypt(content));
System.out.println("解密: " + decrypt(encrypt(content)));
}
}
调用示例
Map<String, String> map = new HashMap<>();
// 业务参数
map.put("app_id", "xxxx");
map.put("app_secret", "xxxx");
// 公共参数
map.put("once_str", EncryptSign.generateOnceStr());
map.put("timestamp", String.valueOf(System.currentTimeMillis()));
// AES加密参数封装到 sign 字段
Map<String, String> param = new HashMap<>();
param.put("sign", EncryptAES.encrypt(toJSONString(map));
// Http 调用
String url = "http://xxx/xx/xx";
String result = HttpClientUtil.httpPost(url, param);
System.out.println(result);
边栏推荐
猜你喜欢

数学工具-desmos 图形曲线

双链表(普通迭代器和常性迭代器)

Server-Sent Events 一种轻量级的Push方式

Based on the matrix calculation in the linear regression equation of the coefficient estimates

implement tcp copa on ns3

剑指offer:在O(1)时间删除链表结点

idea同时修改相同单词

深入理解负载均衡

Evaluation multipath weswood congestion control on ns3

Doubled and sparse tables
随机推荐
Codeforces Round #624 (Div. 3)
idea同时修改相同单词
Litestar 4D – WebCatalog 7:全自动数据管理
基类和派生类的关系【继承】/多态和虚函数/【继承和多态】抽象类和简单工厂
Test case exercises
net start mysql 服务名无效。
【进程间通信】消息队列
golang内存相关文章-收集
Exotic curiosity-a solution looking - bit operations
深入理解Mysql索引底层数据结构与算法
Unity-Post Processing
Qt | 播放音频文件 QMediaplayer
7. Redis
剑指offer:在O(1)时间删除链表结点
第二十八章:解题技巧
couldn't find 'libflutter.so' --flutter
Ubuntu通过apt安装Mysql
shader入门精要1
在mininet中测试arp欺骗
udp transparent proxy