涉及第三方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的请求。当然选哪个方法还是需要结合本身系统的特性选择合适的方案。

相关推荐
dylan_QAQ9 分钟前
【附录】为什么说 Spring 中 BeanFactory的是延迟加载 和轻量级的?有什么证据?
后端·spring
回家路上绕了弯36 分钟前
深度理解 volatile 与 synchronized:并发编程的两把钥匙
java·后端
程序员清风36 分钟前
ThreadLocal在什么情况下会导OOM?
java·后端·面试
就是帅我不改43 分钟前
基于领域事件驱动的微服务架构设计与实践
后端·面试·架构
JohnYan44 分钟前
Bun技术评估 - 25 Utils(实用工具)
javascript·后端·bun
Xasxxs1 小时前
【网络安全】SQL注入——无列名注入
sql·安全·web安全
我要成为Java糕手1 小时前
支付宝芝麻免押支付集成指南及技术对接验收(Java版)
javascript·后端
anthem371 小时前
3、Python持续集成与部署
后端
用户4099322502121 小时前
如何让你的FastAPI Celery Worker在压力下优雅起舞?
后端·github·trae
anthem371 小时前
5、Python文档生成与API设计
后端