Flask 框架如何直接获取 POST 请求的 JSON 原始数据? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
qq7171891
V2EX    Flask

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

  •  
  •   qq7171891 2016-02-22 13:09:21 +08:00 27286 次点击
    这是一个创建于 3584 天前的主题,其中的信息可能已经有所发展或是发生改变。
    自己做了个小网站接了第三方服务,第三方服务会 POST 一个 JSON 过来参与签名加密,我必须获取第三方 POST 过来的 JOSN 的原始数据才能正确效验。

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

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

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

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


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

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

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

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

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


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

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

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

    但是 V2EX 貌似没私信啊~~能否告诉我你们的支付宝账号?
    qq7171891
        19
    qq7171891  
    OP
       2016-02-22 15:17:46 +08:00
    哦。。忘记说了。
    @baocaixiong 30 ,其余每人 20 。钱不多,聊表心意。支付宝是邮箱账号的话公布出来应该没啥问题吧。。
    真希望 V2EX 开个打赏功能。。。
    td width="48" valign="top" align="center">windfarer
        20
    windfarer  
       2016-02-22 15:22:55 +08:00 via iPhone   1
    问题解决了就好,何必客气嘛
    mulog
        21
    mulog  
       2016-02-22 15:24:51 +08:00   1
    楼主好人啊 赞
    不过呢建议你还是善用搜索 google 'flask get raw request data' 出来第一条就有答案告诉你 request.get_data()
    qq7171891
        22
    qq7171891  
    OP
       2016-02-22 15:36:59 +08:00
    @windfarer 谢谢。

    以上楼层有用答案的我都送铜币了,一层送一份,不管是不是同一个人。

    后续我看到本帖之前说的几位前辈有留支付宝账号的,我会立刻发红包。

    再次感谢各位。
    baocaixiong
        23
    baocaixiong  
       2016-02-22 15:39:16 +08:00   1
    @qq7171891 不客气,楼主好好学习
    lixiaohan
        24
    lixiaohan  
       2016-02-22 15:47:31 +08:00
    request.get_data() 看源码 或者官方文档就有
    http://www.pythondoc.com/flask/api.html
    shajiquan
        25
    shajiquan  
       2016-02-22 16:01:35 +08:00
    @qq7171891 不客气。互相交流。
    jixiangqd
        26
    jixiangqd  
       2016-02-22 16:15:05 +08:00
    楼主真是太客气了,铜币已收到, rmb 就算了~v2 就是用来交流技术的嘛,你给钱不坏了风气。。。顺手回一下而已。
    现在用 django 比较多,可能记混了,忘了 flask 的 raw_data 的取值方式,可能有些误导了,抱歉,哈哈哈。。
    WhyLiam
        27
    WhyLiam  
       2016-02-23 11:47:11 +08:00
    为什么我不记得 ping++ Webhooks 要这么复杂
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3211 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 11:25 PVG 19:25 LAX 03:25 JFK 06:25
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86