API 验证签名时,若 payload 的 json value 为复杂对象时该如何处理?

2020-01-16 22:15:15 +08:00
 LinJunzhu

提供 API 给客户端使用时,为了验证是客户端发起的请求,并且保证请求中不被用户恶意串改,我们一般会这么做:

客户端:

1、将请求参数按照 key 字典序排序,将所有 key=value 进行拼接 2、将 [ secret ] [ nonce ] [ timestamp ] 和上述的参数进行拼接

最终将这个字符串通过 sha1/或其他算法 生成一个 token

服务端:

接受到对应的参数时,根据同样的逻辑,生成 token,验证 token 是否一致。

若是下面的参数,会拼接成:aello=world&bello=java

{
	"aello": "world",
	"bello": "java
}

但是若 value 是数组,或是一个对象时,该如何拼接呢?

{
	"aello": "world",
	"bello": {
    	"hi": "hi"
    }
}

翻看了微信和支付宝的文档,两者的参数类型都是基本类型,无数组和对象,但是我们自己在实现过程中,偶尔难免会有复杂结构的 json 参数。

不知道大家是如何做的?

9086 次点击
所在节点    程序员
70 条回复
niubee1
2020-01-18 13:00:08 +08:00
用类似 Merkle tree 的方式嘛,如果一个属性的值是一个对象的话,就替换为对象的 hash 值,而 hash 这个子对象的规则呢就用属性值按照字典序排列 hash 的方式,逐级递归。 这样子就能够保证签名的值不会因为字典解析的 key 是无序的而导致实际内容一致而签名不一致的情况
momocraft
2020-01-18 13:30:23 +08:00
有 https 后还要这样做 图什么
gamexg
2020-01-18 14:55:38 +08:00
body 存放 json,
签名放到 http 头里面
tanszhe
2020-01-18 14:59:33 +08:00
@LinJunzhu 字符串是有序的啊,解析成对象的时候 保持不变就可以了
Orenoid
2020-01-18 15:24:15 +08:00
楼主能不能给我解下惑,我真的没明白你说的防篡改是出于什么需求。。
微信支付我也做过,它那里头的签名的核心部分是商户密钥,本质上是为了身份认证。
如果你只是单纯给业务数据做个签名发给服务端,任何人知道签名算法的话,完全可以脱离客户端伪造一个请求啊。
真心没理解,望解惑。
jss
2020-01-18 16:42:08 +08:00
没有任何意义
jss
2020-01-18 16:43:28 +08:00
不会改参数的不说,会改的防不住...
tairan2006
2020-01-18 21:18:35 +08:00
这玩意儿其实没啥意义,你不用非要抄微信,自己写一个也行…
aaronlam
2020-02-12 02:25:18 +08:00
我之前也纠结过这个问题,持续关注
huobazi
2020-08-11 16:51:42 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/638565

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX