Python根据传入参数生成签名
nonce:客户端随机生成的值,作为参数传递过来,目的是增加sign签名的多变性。随机值一般是数字和字母的组合。
sign:签名参数,防止参数被非法篡改,最常见的是修改金额等敏感参数。sign的值一般是将所有非空参数按升序排序后+token+key+timestamp+nonce拼接在一起,再使用某种加密算法进行加密,作为接口中的一个参数sign或放在请求头中进行请求。
接口在网络传输过程中如果被黑客挟持,并修改其中的参数值,然后再继续调用接口,虽然参数的值被修改了,但是因为黑客不知道sign是如何计算出来的,不知道sign都有哪些值构成,不知道以怎样的顺序拼接在一起的,最重要的是不知道签名字符串中的key是什么,所以黑客可以篡改参数的值,但没法修改sign的值,当服务器调用接口前会按照sign的规则重新计算出sign的值然后和接口传递的sign参数的值做比较,如果相等表示参数值没有被篡改,如果不等,表示参数被非法篡改了,就不执行接口了。
为简略将token、key的参数去除,仅以参数升序+timestamp作加密
构造签名步骤:
import time
import json
import hashlib
import secrets
def sign(body: str, ts: int) -> str:
'''构造签名
:param body: 请求参数,JSON字符串
:param ts: 时间戳,int类型
:return: 签名字符串
>>> sign('{"cityname":"苏州","dtype":"1","params":{"format":"1"}}', 1596666666)
'bcd9e5778bff35f5689c47086895fbca'
'''
body = json.loads(body)
body = {k: body[k] for k in sorted(body)} # 对键值对排序(顺序)
body = json.dumps(body, separators=(',', ':'), ensure_ascii=False) # 转JSON字符串。不允许,和:后有空格
args = {
'key': 'Gjb9UH_OTflkGqLdLk-ofN_LF2TVch7xFrNZb1YJX3I',
'timestamp': ts,
'body': body
} # 固有参数,内容自行决定
args = {k: args[k] for k in sorted(args)} # 对键值对排序(顺序)
sign = '&'.join(['{0}={1}'.format(k, v) for k, v in args.items()]) # 拼接签名字符串
sign = hashlib.md5(sign.encode('utf-8')).hexdigest() # md5算法
return sign
if __name__ == '__main__':
body = '{"cityname":"苏州","dtype":"1","params":{"format":"1"}}' # 请求参数
ts = 1596666666 # 时间戳
print(sign(body, ts)) # 传入请求参数和时间戳生成签名
... # 做后续请求