API 实现参数签名验证
什么是 API 参数签名
- 客户端向服务端发送 API 请求时,为了防止参数被篡改,在请求前将参数进行签名,并将签名随参数一起发送给服务端
- 服务端收到请求后,通过签名算法对签名进行验证,从而判断参数是否被篡改
- 如果签名验证不通过,表示参数被篡改,拒绝请求。
安装插件
- 我们可以使用插件来实现参数签名验证
- 访问官方插件市场,下载
参数签名验证插件

- 将下载的插件拷贝到
DBAPI安装目录下的extlib目录,并重启 DBAPI 服务
API 配置
- 修改 API

- 添加一个
string类型的参数sign,用于存放签名。

全局插件-参数处理中选择此插件,并填写插件参数
json
{ "algorithm": "md5", "secretKey": "123456" }
注意这个
secretKey是跟客户端约定好的字符串密钥,除了给指定客户端使用,不能泄露给任何人,客户端需要用此密钥来计算签名sign
客户端如何使用
- 客户端在访问 API 的时候,需要将所有参数名(除了
sign外)和secretKey先进行字典顺序排序 - 然后将上一步的每个参数名和参数值用
=拼接 - 上一步得到的每一个字符串再用
&符号拼接起来 - 上一步得到的字符串用加密算法(具体采用哪个算法,取决于 API 的插件参数填写的
algorithm)加密,得到一个新的字符串,这个字符串作为参数sign的值,要传给 API - DBAPI 接受到请求后,插件就会用同样的方式拼接参数字符串,然后加密成一个字符串,与
sign值进行比较,如果相同,表示参数没有被篡改,可以继续处理请求,否则拒绝请求
客户端调用 API 示例
需求
- API 定义了 3 个参数
nameagesign, 此 API 使用了签名验证插件并填写了插件参数值{"algorithm": "md5", "secretKey": "123456"} - 您需要访问此 API 并传递以下参数
json
{ "name": "John", "age": 18 }实现
- 先将
nameagesecretKey按字典顺序排序得到["age","name","secretKey"] - 按顺序拼接每个参数的名称和值得到字符串
age=18&name=John&secretKey=123456 - 将字符串
age=18&name=John&secretKey=123456使用md5算法加密得到字符串fa2ffa3f33779f2453e5da82c671ce6a - 将字符串
fa2ffa3f33779f2453e5da82c671ce6a作为 sign 参数值传入 API - 也就是访问 API 的时候必须发送实际的参数为
json
{ "name": "John", "age": 18, "sign": "fa2ffa3f33779f2453e5da82c671ce6a" }- 以 python 为例的访问 API 代码如下
python
import hashlib
import requests
from urllib import parse
# 原始参数值
params = {"name": "John", "age": 18}
# 添加secretKey
params["secretKey"] = "123456"
# 取出所有参数名
keys_list = list(params.keys())
# 对参数名进行排序
keys_list = sorted(keys_list)
# 将每个键和值用 = 拼接,然后用 & 拼接
result = '&'.join(f"{key}={params[key]}" for key in keys_list)
print(result) # age=18&name=John&secretKey=123456
#使用md5算法加密
sign = hashlib.md5(result.encode()).hexdigest()
print(sign) # fa2ffa3f33779f2453e5da82c671ce6a
# params删除secretKey
params.pop("secretKey")
# 添加sign
params["sign"] = sign
print(params) # {'name': 'John', 'age': 18, 'sign': 'fa2ffa3f33779f2453e5da82c671ce6a'}
# 将{'name': 'John', 'age': 18, 'sign': 'fa2ffa3f33779f2453e5da82c671ce6a'}作为参数访问API
requestUrl = 'http://127.0.0.1:8520/api/xxx'
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
data = parse.urlencode(params, True)
response = requests.post(requestUrl, headers=headers, data=data)
print(response.status_code)
print(response.text)