项目场景:
客户端:requests
服务端:Flask
客户端发请求前对请求签名,服务端对签名进行校验
问题描述
服务端签名校验失败,即生成的签名与客户端的不一致
原因分析:
假设我们的请求体为
data = {
"a": "你好"
}
在对字典数据进行json序列化时使用了如下代码
json.dumps(data, ensure_ascii=False)
其中的ensure_ascii参数是控制是否在序列化时使用ascii编码,默认为使用。效果就是中文字符全部变为unicode编码,这是因为中文字符不在ascii编码中。
'{"a": "\\u4f60\\u597d"}'
json序列化后对其进行签名,得到signature
再通过requests将请求发送出去
requests('http://xx.xx.xx.xx', json=data)
可能你已经发现问题了:requests中的json=data默认是使用ascii编码的,所以这就导致服务端进行签名时使用的请求体与客户端的不一样,签名必然失败(有非ascii字符时)
解决方案:
统一签名和发送请求时的序列化规则即可
json.dumps(data, ensure_ascii=False)
requests(..., data=json.dumps(data, ensure_ascii=False).encode('utf-8'))
或
json.dumps(data, ensure_ascii=True)
requests(..., json=data)