如何给API签名

2023-09-20 11:57:50

前言

有时候为了保护API,需要用到 API 签名,使用 API 签名的好处:

  • 让API只能被特定的人访问
  • 防止别人抓包拿到请求参数,通过篡改参数发起新的请求

客户端过程

  1. 给API调用者分配一个app_idapp_secretapp_secret调用者和服务端各保存一份,不对外泄露,app_id需要在调用 API 时作为参数传递。
  2. 除了app_id参数以外,另外增加noncetimestamp参数。timestamp是时间戳,nonce是一个随机字符串,每次调用API时都要重新生成,且需要保证唯一性。这两个参数主要用来防止重复请求。
  3. 将参数列表按字典升序排列,然后在末尾添加上app_secret参数,将参数列表拼接成一个字符串,对字符串做md5加密,得到signature签名,最后将签名也传递给API。

将参数列表拼接成字符串,可以有多种实现方法,在本文中我们使用这种方案:
1)将参数列表进行排序,按key字典升序排列
2)在末尾添加上app_secret参数
3)按key1=value1&key2=value2&key3=value3的格式,将参数列表拼接成一个字符串,其中value值要经过url编码处理
4)拼接完成后,做md5运算,生成散列值,此值便是签名

服务端过程

  1. 收到请求后,按照app_id参数查询到对应的app_secret
  2. 判断timestamp参数是否已过期
  3. 判断nonce参数是否已经被使用
  4. 剔除sign参数,将其它参数按照约定的签名计算方法,生成一个签名A,将签名Asign参数进行对比,如果一致则通过
  5. nonce参数标记为已使用(可以使用redis来存储,并设置过期时间)

注:
1)时间戳的超时时间不能设置得太小,需要考虑服务端和客户端时间可能会有时差的情况,推荐设置为5分钟
2)对于nonce参数,redis key的过期时间一定要大于时间戳的过期时间,比如时间戳过期时间是5分钟,那么redis key的过期时间就要 >= 5分钟

PHP代码示例

client.php
<?php

function genSignature(array $signArr, $appSecret): string
{
    ksort($signArr, SORT_STRING);
    $signArr['app_secret'] = $appSecret;

    $signStr = http_build_query($signArr);
    return md5($signStr);
}

function buildParams(array $params): array
{
    $appId = 'xxxx';
    $appSecret = 'yyyy';

    $params['app_id'] = $appId;
    $params['nonce'] = uniqid('', true);
    $params['timestamp'] = time();
    $params['sign'] = genSignature($params, $appSecret);

    return $params;
}

$params = [
    'username' => '小明',
    'gender' => '男',
];
var_dump(buildParams($params));

// TODO:使用生成的参数调用API接口

server.php
<?php

function signatureVerify(array $signArr, $appSecret): string
{
    unset($signArr['sign']);

    ksort($signArr, SORT_STRING);
    $signArr['app_secret'] = $appSecret;

    $signStr = http_build_query($signArr);
    return md5($signStr);
}

$params = $_GET;

$appId = $params['app_id'];
// TODO:根据app_id参数查找对应的app_secret
$appSecret = 'yyyy';

$mySign = signatureVerify($params, $appSecret);
if ($mySign === $params['sign']) {
    echo '签名验证成功';
} else {
    echo '签名验证失败';
}

// TODO:检查timestamp是否已过期
// TODO:检查nonce是否已被使用过
// TODO:将nonce存储到redis,并设置key的过期时间

关于app_secret的安全性

在上述整个过程中,最重要的是保证app_secret不外泄,如果app_secret外泄了,其他人就可以用它来生成签名。

但真实情况下,我们很难保证app_secret不外泄,如果客户端是server端还好说,但如果客户端是浏览器的话,由于网页代码都是可以被看到的,所以只要查看一遍网页的js代码,就可以找到app_secret

如果客户端是安卓APP,别人也可以通过拆解apk安装包,破解拿到app_secret

面对这种情况也没有完美的方法,毕竟源代码都被别人看到了,还能有啥安全可言。只能通过js代码混淆、apk包安全加固等方法来提高别人找到app_secret的难度。

加密

虽然我们给接口加了签名验证,但别人还是可以通过浏览器的开发者工具、或者抓包看到具体传递的参数名和参数值。

如果不想别人看到这些信息的话,可以将参数都加密,加密方法可以使用RSA加密(使用服务端公钥加密,服务端收到请求后使用私钥解密)、或者AES加密。

加密后,别人抓包看到的就都是密文了,可以提高别人破解接口的难度。

更多推荐

STM32WB55开发(2)----修改蓝牙地址

STM32WB55开发----2.修改蓝牙地址概述硬件准备视频教学样品申请完整代码下载选择芯片型号配置时钟源配置时钟树RTC时钟配置查看开启STM32_WPAN条件配置HSEM配置IPCC配置RTC启动RF开启蓝牙设置工程信息工程文件设置修改置BLE设备公共地址Ble_Hci_Gap_Gatt_Init结果演示概述在嵌

【STM32】驱动库的选择:CMSIS Driver、SPL、HAL、LL | 在ARM MDK、STM32Cube中如何选择?

阅读本专栏其他文章,有助于理解本文。👆文章目录一、开发库选择1.1概述1.2CMSISpack1.3SPL库1.4HAL库1.5LL库1.6寄存器开发二、代码对比2.1使用寄存器2.2使用CMSIS库2.3使用SPL库2.4使用HAL库2.5使用LL库2.6使用RTOS三、如何在软件中选择不同的库3.1ARMMDK3

Spring Boot自动装配原理

简介SpringBoot是一个开源的Java框架,旨在简化Spring应用程序的搭建和开发。它通过自动装配的机制,大大减少了繁琐的配置工作,提高了开发效率。本文将深入探讨SpringBoot的自动装配原理。自动装配的概述在传统的Spring框架中,我们需要手动配置各种组件和依赖关系。而SpringBoot则通过自动扫描

基于微信小程序的高校就业招聘系统设计与实现(源码+lw+部署文档+讲解等)

前言💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗👇🏻精彩专栏推荐订阅👇🏻2023-2024年最值得选的微信小程序毕业设计选题大全:100个热门选

c++Flood Fill算法之池塘计数,城堡问题,山峰与山谷(acwing)

FloodFill算法有很多应用场景,以下是一些常见的应用场景:1.图像处理:在图像处理中,我们通常需要对图像的某一个区域进行涂色、填充、描边等操作,FloodFill算法就可以用来实现这些操作。2.游戏开发:在游戏中,FloodFill算法可以用来实现区域填充、地图探索、迷宫求解等功能。3.自动化绘制:FloodFi

如何用ate自动测试设备对DC-DC电源模块负载调整率进行测试?

电源模块负载调整率测试是功能测试之一,是电源模块非常重要的一项指标,它的大小直接影响着电源模块的整体质量。因此使用ate自动测试设备对DC-DC电源模块负载调整率进行测试是制造生产过程中至关重要的一环。电源模块负载调整率计算公式:负载调整率=(满载输出电压-空载输出电压)/额定输出电压*100%测量电源模块的负载调整率

解决高并发问题

在处理项目中的高并发问题时,可以采取以下几种方法:后端处理:大部分的高并发处理是在后端进行的。可以通过优化数据库查询、增加缓存机制(如集成Redis)、使用分布式技术(如分布式缓存、分布式锁)、使用消息队列等方式来提高系统的并发处理能力。此外,还可以通过水平扩展(增加服务器数量)或垂直扩展(增加服务器的硬件配置)来提高

Kafka【命令行操作】

Kafka命令行操作Kafka主要包括三大部分:生产者、主题分区节点、消费者。1、Topic命令行操作也就是我们kafka下的脚本kafka-topics.sh的相关操作。常用命令行操作参数描述--bootstrap-server<String:servertoconnectto>连接的KafkaBroker主机名称和

【Android Framework系列】第15章 Fragment+ViewPager与Viewpager2相关原理

1前言上一章节【AndroidFramework系列】第14章Fragment核心原理(AndroidX版本)我们学习了Fragment的核心原理,本章节学习常用的Fragment+ViewPager以及Fragment+ViewPager2的相关使用和一些基本的源码分析。2Fragment+ViewPager我们常用

腾讯mini项目-【指标监控服务重构】2023-07-19

今日已办OpenTelemetryLogs通过日志记录API支持日志收集集成现有的日志记录库和日志收集工具Overview日志记录API-LoggingAPI,允许您检测应用程序并生成结构化日志旨在与其他telemertydata(例如metric和trace)配合使用,以提供统一的可观测性解决方案结构化日志记录,允许

预处理代码

一、缺失值处理删除缺失值:data1=data.dropna()#丢弃缺失值#dropna()删除缺失值所在行(axis=0)或列(axis=1),默认为axis=0补全示例数据:importpandasaspdimportnumpyasnpdata=pd.DataFrame({'name':['Bob','Mary'

热文推荐