接口签名如何处理

期望效果

  1. 统一处理,无需每个接口单独处理。

实现思路

  1. 创建一个 公共脚本 实现签名逻辑,读取接口请求参数,然后使用 内置类库,如(crypto-js接口签名如何处理 - 图1),生成签名。
  2. 将生成的签名 sign 作为参数加入请求,可使用以下两种方案:
    • 方案一:脚本直接修改请求信息,注入一个签名参数,无需使用环境变量。
    • 方案二:将生成的签名写入环境变量,接口设置参数时引用环境变量。
  3. 在接口的 前置脚本 里引用前面创建公共脚本。
  4. 如果签名算法是其他语言编写的,可使用fox.execute方法 调用其他语言编写的程序

接口签名示例

签名生成规则

本签名规则同 微信支付签名算法接口签名如何处理 - 图2

第一步:假设所有发送参数集合M,将集合M内非空参数值的参数按照参数名 ASCII 码从小到大排序(字典序),使用 URL 键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA

特别注意以下重要规则:

  1. 参数名ASCII码从小到大排序(字典序);
  2. 如果参数的值为空不参与签名;
  3. 参数名区分大小写;
  4. 传送的sign参数不参与签名;

第二步:在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到signsignValue

公共脚本实现

  1. // 获取预先设置为环境变量的 APPKEY
  2. let key = pm.environment.get("APPKEY");
  3. // 存放所有需要用来签名的参数
  4. let param = {};
  5. // 加入 query 参数
  6. let queryParams = pm.request.url.query;
  7. queryParams.each(item => {
  8. if (!item.disabled && item.value !== '') { // 启用且非空参数值的参数才参与签名
  9. param[item.key] = item.value;
  10. }
  11. });
  12. // 加入 body 参数
  13. if (pm.request.body) {
  14. let formData;
  15. switch (pm.request.body.mode) {
  16. case 'formdata':
  17. formData = pm.request.body.formdata;
  18. break;
  19. case 'urlencoded':
  20. formData = pm.request.body.urlencoded;
  21. break;
  22. case 'raw':
  23. // 如果没有 JSON 格式的请求 body,或 JSON 格式 body 不参与签名,可以删除这一段
  24. let contentType = pm.request.headers.get('content-type');
  25. if (
  26. contentType
  27. && pm.request.body.raw
  28. && contentType.toLowerCase().indexOf('application/json') !== -1
  29. ) {
  30. try {
  31. let jsonData = JSON.parse(pm.request.body.raw);
  32. /*
  33. * 注意:通过脚本取出来的接口参数,如果参数包含变量,变量是不会替换成对应的值。如想要获取替换后的值,可使用`pm.variables.replaceIn`方法处理:
  34. * let body = pm.variables.replaceIn(pm.request.body.raw);
  35. * let jsonData = JSON.parse(body);
  36. */
  37. for (let key in jsonData) {
  38. let value = `${jsonData[key]}`; // 此处要注意如果值的实际类型不是 string 需要根据实际情况处理。
  39. if (value !== '') { // 非空参数值的参数才参与签名
  40. param[key] = value;
  41. }
  42. }
  43. } catch (e) {
  44. console.log('请求 body 不是 JSON 格式')
  45. }
  46. }
  47. break;
  48. default:
  49. break;
  50. }
  51. if (formData) {
  52. formData.each(item => {
  53. if (!item.disabled && item.value !== '') { // 启用且非空参数值的参数才参与签名
  54. param[item.key] = item.value;
  55. }
  56. });
  57. }
  58. }
  59. // 取 key
  60. let keys = [];
  61. for (let key in param) {
  62. // 注意这里,要剔除掉 sign 参数本身
  63. if (key !== 'sign') {
  64. keys.push(key);
  65. }
  66. }
  67. // 参数名 ASCII 码从小到大排序(字典序)
  68. keys.sort();
  69. // 转成键值对
  70. let paramPair = [];
  71. for (let i = 0, len = keys.length; i < len; i++) {
  72. let k = keys[i];
  73. paramPair.push(k + '=' + encodeURIComponent(param[k])) // urlencode 编码
  74. }
  75. // 最后加上 key
  76. paramPair.push("key=" + key);
  77. // 拼接
  78. let stringSignTemp = paramPair.join('&');
  79. // console.log(stringSignTemp);
  80. let sign = CryptoJS.MD5(stringSignTemp).toString().toUpperCase();
  81. // console.log(sign);
  82. // 方案一:直接修改接口请求的 query 参数,注入 sign,无需使用环境变量。
  83. // 参考文档:https://www.apifox.cn/help/app/scripts/examples/request-handle/
  84. queryParams.upsert({
  85. key: 'sign',
  86. value: sign,
  87. });
  88. // 方案二:写入环境变量,此方案需要在接口里设置参数引用环境变量
  89. // pm.environment.set("SIGN", sign);

百度翻译接口签名示例

本示例为调用百度翻译接口,百度翻译接口参考文档接口签名如何处理 - 图3

签名生成规则

第一步:将请求参数中的 APPID(appid), 翻译query(q, 注意为UTF-8编码), 随机数(salt), 以及平台分配的密钥(可在管理控制台接口签名如何处理 - 图4查看) 按照 appid+q+salt+密钥 的顺序拼接得到字符串1第二步:对字符串1做md5,得到32位小写的sign。

注:

  1. 待翻译文本(q)需为UTF-8编码
  2. 在生成签名拼接 appid+q+salt+密钥 字符串时,q不需要做URL encode,在生成签名之后,发送HTTP请求之前才需要对要发送的待翻译文本字段q做URL encode
  1. 官方举例:将apple从英文翻译成中文:
  2. 请求参数:
  3. q=apple
  4. from=en
  5. to=zh
  6. appid=2015063000000001
  7. salt=1435660288
  8. 平台分配的密钥: 12345678
  9. 生成sign
  10. >拼接字符串1
  11. 拼接appid=2015063000000001+q=apple+salt=1435660288+密钥=12345678
  12. 得到字符串1 =2015063000000001apple143566028812345678
  13. >计算签名sign(对字符串1md5加密,注意计算md5之前,串1必须为UTF-8编码)
  14. sign=md5(2015063000000001apple143566028812345678)
  15. sign=f89f9594663708c1605f3d736d01d2d4
  16. 完整请求为:
  17. http://api.fanyi.baidu.com/api/trans/vip/translate?q=apple&from=en&to=zh&appid=2015063000000001&salt=1435660288&sign=f89f9594663708c1605f3d736d01d2d4

公共脚本实现

  1. // 获取 Query 参数对象
  2. var queryParams = pm.request.url.query;
  3. // 获取 query 参数 q 的值
  4. var q = queryParams.get('q');
  5. // 获取预先设置为环境变量的 APPID 和 SECRET_KEY
  6. var appid = pm.environment.get("APPID");
  7. var secretKey = pm.environment.get("SECRET_KEY");
  8. // 定义一个随机数(32768, 65536)之间
  9. var salt = parseInt(Math.random() * (32769) + 32768, 10);
  10. // 将随机数转换为字符串
  11. salt = salt.toString();
  12. console.log(salt);
  13. // 定义一个由appid、要翻译的字符串、随机数、密钥组合成一个字符串
  14. var str = appid + q + salt + secretKey;
  15. console.log(str);
  16. // 将 str 进行 md5 加密生成 sign
  17. var sign = CryptoJS.MD5(str).toString();
  18. // 方案一:直接修改接口请求的 query 参数,注入 salt 和 sign,无需使用环境变量。
  19. // 参考文档:https://www.apifox.cn/help/app/scripts/examples/request-handle/
  20. queryParams.upsert({
  21. key: 'salt',
  22. value: salt,
  23. });
  24. queryParams.upsert({
  25. key: 'sign',
  26. value: sign,
  27. });