JSON编解码方式差异是否会影响访问令牌的有效性?
不同语言JSON序列化空白符差异问题解答
差异复现
我们分别用Dart和Python定义相同的JSON对象:
final jsonData = {'access_key':'i-want-to-authorized','param1': 'parameter1'};
jsonData = {'access_key':'i-want-to-authorized','param1': 'parameter1'}
分别执行序列化操作:
import 'dart:convert'; final jsonData = {'access_key':'i-want-to-be-authorized','param1': 'parameter1'}; final dumpedJson = json.encode(jsonData); print(dumpedJson);
import json jsonData = {'access_key':'i-want-to-be-authorized','param1': 'parameter1'} dumped_json = json.dumps(jsonData) print(dumped_json)
得到的输出结果:
- Dart运行输出:
{"access_key":"i-want-to-be-authorized","param1":"parameter1"} - Python运行输出:
{"access_key": "i-want-to-be-authorized", "param1": "parameter1"}
对服务端识别的影响
分两种场景判断:
- 服务端使用标准JSON解析库处理请求:不会出现识别问题
JSON官方规范明确允许键值对冒号前后、逗号前后存在任意数量的空白字符,标准JSON解析器会自动忽略这些无意义的空白符,两种序列化结果解析后得到的结构完全一致,服务端可以正常读取所有字段。
- 以下两种特殊场景会导致请求识别失败:
- 服务端未使用标准JSON解析库,而是通过正则匹配、硬编码字符串截取等非规范方式提取字段:如果服务端代码写死了匹配
"access_key":"这种无空格的格式,Python输出的带空格的"access_key": "就会匹配失败,导致字段读取异常。 - 服务端请求校验逻辑直接对比原始序列化字符串的签名/哈希值:如果签名校验是直接对序列化后的原始字符串做哈希计算后对比,两种带不同空白符的字符串哈希结果完全不同,会直接触发签名校验失败,请求被拒绝。这类场景在各类开放平台API的签名校验逻辑中非常常见。
解决方案
要规避这类序列化差异导致的问题,可以采用以下两种方案:
- 统一序列化格式:Python的
json.dumps方法支持通过separators参数自定义分隔符,添加参数separators=(',', ':')即可输出和Dart默认序列化完全一致的无空格格式:# 输出结果与Dart序列化结果完全一致 dumped_json = json.dumps(jsonData, separators=(',', ':')) - 统一签名基准:如果涉及签名校验,建议先将JSON对象统一按键名升序排序、统一转义规则、统一空白符规则后再序列化计算签名,从根源上避免不同语言的序列化默认规则差异。
内容的提问来源于stack exchange,提问作者CrimsonFoot
相关产品推荐
相关产品推荐

