Flask 框架如何直接获取 POST 请求的 JSON 原始数据?

2016-02-22 13:09:21 +08:00
 qq7171891
自己做了个小网站接了第三方服务,第三方服务会 POST 一个 JSON 过来参与签名加密,我必须获取第三方 POST 过来的 JOSN 的原始数据才能正确效验。

现在是用 Flask 的 request.get_json()去拿 JSON 数据,拿是可以拿到,但是拿到的数据已经不是原始数据了,被重新排序,键值对还加了空格,这样就不是原始的 JSON 了,加密效验也就无法完成。

请求大神指点如何拿到原始的 JSON 数据。当然,要基于 Flask 的 route 。
26759 次点击
所在节点    Flask
27 条回复
windfarer
2016-02-22 13:16:47 +08:00
request.data
qq7171891
2016-02-22 13:27:29 +08:00
@windfarer 拿不到, request.data 仅在无法识别请求 mimetype 时才把数据放到这里面。第三方 POST 过来的数据类型明确是: Content-Type: application/json
cxl008
2016-02-22 13:34:42 +08:00
如果第三方的程序员 直接用字典转成的 json ,那你这不是跪了,再怎么获取都没用啊。。。。
billion
2016-02-22 13:36:02 +08:00
request.get_json()
shidenggui
2016-02-22 13:37:05 +08:00
看了下源码,用 get_json 是用的 requesr.get_data 获取的数据
qq7171891
2016-02-22 13:37:23 +08:00
@billion 兄弟。。题目中说了 request.get_json()会序列化 JSON 格式,序列出来的不是原始数据啊。
qq7171891
2016-02-22 13:44:05 +08:00
@cxl008 不是你理解的。

需求是我方要效验对方接口的签名,以核实请求方的身份。
请求方给我们一个公钥,自己用私钥把请求体的 JSON 进行加密运算,得出签名。对方请求我这边的时候会告诉我签名,以及 JSON ,我去拿对方给的公钥去计算,看看签名符合不符合。

这就要求我从请求拿上来的 JSON 就是对方传给我的,现在的问题是我看了 FLASK 文档半天,只有 request.get_json()这个方法拿 JSON ,但是拿过来的已经是被格式化了的,不是原始数据了。
jixiangqd
2016-02-22 13:46:13 +08:00
用 collections 里的 OrderedDict 反序列化 JSON....


json.load(object_pairs_hook=collections.OrderedDict)
jixiangqd
2016-02-22 13:47:37 +08:00
漏了个参数。。。 request.raw_data 没法编辑原回答,只能再回一次了

json.load(request.raw_data,object_pairs_hook=collections.OrderedDict)
shajiquan
2016-02-22 13:49:37 +08:00
你可以拿到 request body ,但是这个 body 里的 JSON 字符串可能也是乱序的。而且这是无法避免的。

既然如此的话,你就应该改变你的验证策略,比如说, JSON 数据中有一个字段专门就是 md5 之类的摘要,这个摘要是通过另外的值+私钥生成的,到你这边的时候,你根据私钥和 md5 摘要之外的其他数据来生成 md5 摘要,验证那个 md5 摘要是否和你的一致,这样是否 OK ?

有必要时,再在 header 里加入一些标识,或者把 md5 摘要放在 header 里不要放在 json 里。

前段时间我写了一个 API 供调用,用的就是这种思路,没有出现过问题。
ethego
2016-02-22 13:50:14 +08:00
json 对象不本来就是无序的吗?
windfarer
2016-02-22 13:51:05 +08:00
@qq7171891
我刚才试了一下,设置了 Content-Type: application/json 的 header 之后, request.data 里还是有数据的啊,难道是我姿势不正确。。
baocaixiong
2016-02-22 13:52:16 +08:00
request.get_data()
qq7171891
2016-02-22 14:08:13 +08:00
@shajiquan 我也想。我直接说了,这是 pingxx 这个支付网关 Webhooks 回调签名方式,想他们改还是算了。
qq7171891
2016-02-22 14:10:38 +08:00
@windfarer 我再验证下。
qq7171891
2016-02-22 14:30:28 +08:00
@baocaixiong 这个一开始尝试过,转换的数据带了一个 b' 开头,再就是看文档说不推荐就没用了。那个 b' 可以弄掉?
ethego
2016-02-22 14:34:03 +08:00
@qq7171891 没有必要,这是个装饰符,代表字符串的类型是 bytes ,这个符号不会影响数据本身
qq7171891
2016-02-22 15:15:28 +08:00
@ethego 还是需要转换下字符串。


@baocaixiong 谢谢你,怪我错误理解文档轻易放弃这个办法了,用 request.get_data()后转下码方案可行。

另外谢谢:
@windfarer
@shajiquan
@jixiangqd
@windfarer

以上 6 人,特别是 @baocaixiong ,我想给你们发支付宝红聊表心意,感谢你们对我这个初学者的帮助。

但是 V2EX 貌似没私信啊~~能否告诉我你们的支付宝账号?
qq7171891
2016-02-22 15:17:46 +08:00
哦。。忘记说了。
@baocaixiong 30 ,其余每人 20 。钱不多,聊表心意。支付宝是邮箱账号的话公布出来应该没啥问题吧。。
真希望 V2EX 开个打赏功能。。。
windfarer
2016-02-22 15:22:55 +08:00
问题解决了就好,何必客气嘛

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

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

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

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

© 2021 V2EX