首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

坑爹的urlencode

  • 25-04-16 08:40
  • 4444
  • 10810
juejin.cn

故事背景

我们接口有一个sign签名,用来校验接口调用方是不是合作方,sign的规则是就是post的数据按参数名asc值从小到大排序+key,然后算md5。我们接口文档已经写了java版本的demo,前端那边需要有个js版本的demo,然后我们尝试写了下demo,发现坑很多。

java部分代码:

java
代码解读
复制代码
JSONObject json = JSON.parseObject(input); //TreeMap自动把参数排序         TreeMap data = new TreeMap();         for (String key : json.keySet()) {             if ("sign".equals(key)) {                 //sign不参与签名                 continue;             }             data.put(key, json.getString(key));         }         List params = new ArrayList();         // 重组参数         for (String key : data.keySet()) {             String value = String.format("%s=%s", key, data.get(key));             params.add(value);         }         // 组合参数和签名 secret_key         String temp = URLEncoder.encode(StringUtils.join(params, "&").toLowerCase() + "&key=" + secret_key);         String result = encode(temp);

AI辅助编写代码

把java的签名规则转换成js的签名规则,可以使用AI工具直接生成,下面是我用CHATGPT生成的JS代码。

js
代码解读
复制代码
const crypto = require('crypto'); // input: 接口传入的JSON字符串 // secret_key: 用于签名的密钥 function calculateSign(input, secret_key) { // 解析 JSON 字符串 const json = JSON.parse(input); // 将参数放入一个对象并按键名排序 const data = {}; Object.keys(json) .sort() // 按字典顺序排序 .forEach((key) => { if (key !== 'sign') { data[key] = json[key]; } }); // 重组参数 const params = []; for (const key in data) { params.push(`${key}=${data[key]}`); } // 拼接参数和 secret_key const temp = encodeURIComponent( params.join('&').toLowerCase() + `&key=${secret_key}` ); // 计算 MD5 签名 const hash = crypto.createHash('md5'); hash.update(temp); const result = hash.digest('hex'); return result; } // 示例调用 const input = '{"param1":"value1","param2":"value2","sign":"abcd1234"}'; const secret_key = 'my_secret_key'; const sign = calculateSign(input, secret_key); console.log('签名:', sign);

一眼看过去好像没什么问题,但是测试的时候发现有很多坑...

首先请求参数的格式有可能是个数组,比如"test" :[{"test1":"xxx"}]这种,直接获取json的时候只会获取到object,需要做一下转换

js
代码解读
复制代码
if (Array.isArray(json[key])) { // 如果值是数组,将其转换为 JSON 字符串 data.set(key, JSON.stringify(json[key])); } else { // 否则,直接设置值 data.set(key, json[key]); }

如果有多重嵌套循环,可以进行递归操作

js
代码解读
复制代码
function processObject(obj) { const result = {}; for (const key in obj) { if (key === "sign") { continue; } const value = obj[key]; if (Array.isArray(value)) { result[key] = value.map(item => { if (typeof item === 'object') { return processObject(item); } return item; }); } else if (typeof value === 'object') { result[key] = processObject(value); } else { result[key] = value; } } return result; }

urlEncode的坑

解决了数组解析成object的坑,兴高采烈地校验签名,发现签名还是不一样,md5的代码规则是一样的,最后一对比发现urlencode后的字符串是不一样的,这让我回想起两年前跟合作方对接的时候也遇到这个问题,当时他们是用的GO语言,他说他们GO语言号是要转义的,我发了个网址给他说号不用转义呀。www.jsons.cn/urlencode

他也发了一个地址给我说java特殊处理了。

stackoverflow.com/questions/6…

我一看源码真的是

image.png

数字字母,' '空格变+加号,还有"-" , "_", "." , "*"

因为我们是服务端,是公共的接口对接多个合作方,所以要他们兼容我们规则,规则说清楚就行了。

现在又来了一个前端的urlencode...查了一下前端是用了encodeURIComponent这个方法,该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。

还好看起来规则差不多,最后用一个replace大法把有差异的编码做一个适配。

js
代码解读
复制代码
const originalEncodeURIComponent = encodeURIComponent; encodeURIComponent = function (str) { const encoded = originalEncodeURIComponent(str); return encoded.replace(/%20/g, '+') //空格 .replace(/!/g, '%21') //! .replace(/\(/g, '%28') //( .replace(/\)/g, '%29')//) .replace(/~/g, '%7E')//~ .replace(/'/g, '%27');//' }

总结

不知道为什么,这个urlencode居然没有一个统一的标准,导致JAVA、GO和JS都有不一样的规则,如果要对接urlencode就会有一些编码对不齐,不过用urldecode会获得一样的结果......

使用AI编程的时候一定要多测试,因为他的代码很可能有不少bug~

注:本文转载自juejin.cn的玛奇玛丶的文章"https://juejin.cn/post/7493065425467555840"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top