Python根据传入参数生成签名

文章目录

  • 问题描述
  • 解决方案
  • 代码
  • 参考文献

问题描述

Python根据传入参数生成签名




解决方案

nonce:客户端随机生成的值,作为参数传递过来,目的是增加sign签名的多变性。随机值一般是数字和字母的组合。

sign:签名参数,防止参数被非法篡改,最常见的是修改金额等敏感参数。sign的值一般是将所有非空参数按升序排序后+token+key+timestamp+nonce拼接在一起,再使用某种加密算法进行加密,作为接口中的一个参数sign或放在请求头中进行请求。

接口在网络传输过程中如果被黑客挟持,并修改其中的参数值,然后再继续调用接口,虽然参数的值被修改了,但是因为黑客不知道sign是如何计算出来的,不知道sign都有哪些值构成,不知道以怎样的顺序拼接在一起的,最重要的是不知道签名字符串中的key是什么,所以黑客可以篡改参数的值,但没法修改sign的值,当服务器调用接口前会按照sign的规则重新计算出sign的值然后和接口传递的sign参数的值做比较,如果相等表示参数值没有被篡改,如果不等,表示参数被非法篡改了,就不执行接口了。




代码

为简略将token、key的参数去除,仅以参数升序+timestamp作加密

构造签名步骤:

  1. 对body升序排序
  2. 固有参数放入body和时间戳
  3. 对固有参数顺序排序
  4. 拼接固有参数得到签名字符串
  5. 加密算法计算签名字符串获得签名
  6. 将签名放入参数或请求头中
  7. 发送请求
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))  # 传入请求参数和时间戳生成签名
    ...  # 做后续请求







参考文献

  1. Java生鲜电商平台-API接口设计之token、timestamp、sign 具体架构与实现
  2. hashlib — 安全哈希与消息摘要

你可能感兴趣的:(Python)