涉及第三方Api加密通信,我连夜设计了一套让领导满意的方案

我们在项目开发的时候难免会与第三方对接,而与第三方直接的接口通讯大多数为http方式的通讯方式,那么这个时候就有个问题,两个系统直接的接口数据怎么进行校验呢,如何防止拿到接口的人通过技术手段调用呢?例如使用postman等的方式调用。

那么这篇文章就会以两种角色的角度带大家走入接口之间的安全校验机制------API提供方(服务端)API调用方(客户端) ,分别探讨如何设计安全的接口交互方案。 那么本文做的示例就是使用 AK(api id)/SK(secret key) 签名认证API 接口。

首先我们要定义一套参数加密方案,加密方案有很多,例如

算法类型 安全性 计算速度 输出长度 适用场景
MD5 最快 128bit 不推荐新系统使用
SHA1 160bit 旧系统兼容
SHA256 256bit 推荐默认选择
SHA3 极高 较慢 可变 高安全要求
HMAC 可变 带密钥签名
RSA 极高 可变 非对称场景
ECDSA 极高 较慢 256/512bit 区块链等

那么作为我们这篇文章的嘉宾,我们邀请到了SHA1选手

作为API提供方

作为API提供方我们需要考虑的事是我作为供应商会有很多的客户,而每个客户肯定要有一个专门的标识,那么我们就可以通过 AK(api id) 去区分每一个客户。而我们也会提供每一个AK对应的密码,即 SK(secret key) ,而这个两个内容我们肯定是需要我们作为提供方去存储起来的,而我们的客户(即调用方)我们也会提供一个AK和SK给他们。

我们需要定义一套规则,让客户需要把所有的参数组成一个字符串然后在进行sha1签名,然后我们拿到业务参数后我们也进行sha1签名,如果最后出来的字符串内容是一样的化,则说明验证通过,我们继续拿到他的业务参数进行下一步的操作。

而我们与客户的交互参数中有三个参数是最重要的,如AK(api id)SK(secret key)时间戳

  • AK → "你是谁"(认证)
  • SK → "你真的是你"(防伪)
  • 时间戳 → "你的请求是否新鲜"(防重放)

而有了这个三个参数加上客户的业务参数就组成了一个字符串然后再进行sha1签名,就得到了一个加密过后的sha1字符串,然后在把这个sign(签名串)添加到参数中请求我们,我们就可以进行接口校验,从而达到系统交互之间的安全交互。

作为调用方

上面我们讲了作为服务提供方提供的方案,那么我们如果要想签名认证通过的话我们是需要使用和提供方一样的签名方案的。而这个签名方案一般都是提供方提供的,我们只需要根据他的对接文档进行对接即可

首先我们要确认的提供方的一个加密方案,例如上面提供的方案:

参数1=值1&参数2=值2&ak=xxx&时间戳=xxx

再把上面的值进行sha1 加密,即可生成一个sign:

java 复制代码
    private String sha1(String input) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            byte[] result = digest.digest(input.getBytes());
            StringBuilder sb = new StringBuilder();
            for (byte b : result) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("SHA-1 algorithm not found", e);
        }
    }

例如提供方的接口需要的业务参数是这样的:

json 复制代码
{
  "参数1": 1234,
  "参数2": "dr576f8",
  "参数3": "fefeww"
}

而一般还需要添加三个参数:

json 复制代码
{
  "app_id": "342345",
  "timestamp": 1739345600,
  "sign": "aa442339f6535e635c2a62cd035d25bfa8771bcc"}

sign就是我们上面把业务参数组装好之后经过sha1计算出来的签名, 把这个也加入到请求体中,最后的请求body为:

json 复制代码
{
  "参数1": 1234,
  "参数2": "dr576f8",
  "参数3": "fefeww",
  "app_id": "342345",
  "timestamp": 1739345600,
  "sign": "aa442339f6535e635c2a62cd035d25bfa8771bcc"
}

其中我们的sk是加入到sign签名里面去的,所以没有直接暴露在请求体中。这样,提供方就知道了以下内容

  • AK → "你是谁"(认证)
  • SK → "你真的是你"(防伪)
  • 时间戳 → "你的请求是否新鲜"(防重放)
  • 业务参数 → "具体你要干什么"(业务请求)

这样一套api的验证机制就做好了,如果我们有回调接口的话我们则会和提供方保持一样的验证方式,那么则需要提供方在回调我们的接口的时候也吧上面四个内容传过来,这样就能保证双方的api安全了。一般我们会把回调地址以业务参数的形式传递给提供方。

除此之外,因为我们都是http的方式进行调用,那么我们难免会遇见像网络错误这种情况,那么我们应该也需要在双方都添加重试机制,如果你是java客户端,可以看看作者之前写过的文章:

如果你需要使用重试机制,请使用Spring官方的Spring Retry

那么最为最后的结尾,这里只是拿sha1举例,其实大家可以换成其他的签名算法也是没有问题的。当调用方和提供方都能遵循这套"数字礼仪",三方系统间的对话才能真正做到既安全又流畅。

如果非要弄简单的不需要鉴权的api接口,则可以考虑添加白名单机制,即把调用方的ip地址加入白名单,拒绝掉非此ip的请求。当然选哪个方法还是需要结合本身系统的特性选择合适的方案。

相关推荐
爱宇阳2 小时前
Linux 安全加固:设置命令行无操作超时退出
linux·运维·安全
龙亘川3 小时前
【课程3.4】高可用架构保障:Control节点、存储平面、安全防护的架构选型
安全·平面·架构·智慧城市
9号达人3 小时前
Jackson序列化让验签失败?破解JSON转义陷阱
java·后端·面试
LambHappiness3 小时前
Grafana LDAP配置故障排查:从3小时到10分钟的AI辅助解决方案
后端
她说..4 小时前
Spring AOP场景3——接口防抖(附带源码)
java·后端·spring·java-ee·springboot
海上彼尚4 小时前
Go之路 - 7.go的函数
开发语言·后端·golang
martinzh4 小时前
NL2SQL解决了?别闹了!大模型让你和数据库聊天背后的真相
后端
靓仔建4 小时前
在asp.net web应用程序,老是访问同一个Handler1.ashx
后端·asp.net·一般处理程序
QK芒果小洛4 小时前
Springboot 接口校验数组中的对象的方式
java·spring boot·后端