和光同尘789 2024-08-01 11:13 采纳率: 100%
浏览 38
已结题

带防重放token(Antireplay-Token)的网站怎么用Python发送请求

发送的请求带Antireplay-Token,每次都不一样,看了下是调用的js里的方法生成的,我用python如何获取这个token并发送请求获取系统数据?求指导
可以Python直接重现JavaScript的生成逻辑吗?还是只能通过浏览器模拟的方式?长度受限,部分 javascript代码:
ui.js

getReplayToken = function() {
 time = (Date.now() - window.backTimeOffset).toString();
 random = time.slice(-9) + Math.random().toString().slice(2, 8);
 str = random + "|" + time;
 return window.sm4.encrypt(str, sm4Key)

sm4.js

var encrypt = function encrypt(data, key, options) {
  var _convertOptions = convertOptions(options, 'encrypt'),
      mode = _convertOptions.mode,
      iv = _convertOptions.iv,
      inputEncoding = _convertOptions.inputEncoding,
      outputEncoding = _convertOptions.outputEncoding,
      padding = _convertOptions.padding;

  if (!key) {
    key = '20141131201411312014113120141131';
  } 


  if (typeof data === 'string') {
    data = buffer__WEBPACK_IMPORTED_MODULE_1__.Buffer.from(data, inputEncoding || 'utf8');
  } else if (data instanceof ArrayBuffer) {
    data = buffer__WEBPACK_IMPORTED_MODULE_1__.Buffer.from(data);
  } else if (Array.isArray(data) && inputEncoding === 'array') {
    var hexStr = '';

    var _iterator = _createForOfIteratorHelper(data),
        _step;

    try {
      for (_iterator.s(); !(_step = _iterator.n()).done;) {
        var item = _step.value;
        var str = item.toString(16);

        if (str.length === 1) {
          str = '0' + str;
        }

        hexStr += str;
      }
    } catch (err) {
      _iterator.e(err);
    } finally {
      _iterator.f();
    }

    inputEncoding = 'hex';
    data = buffer__WEBPACK_IMPORTED_MODULE_1__.Buffer.from(hexStr, inputEncoding);
  }

  if (!buffer__WEBPACK_IMPORTED_MODULE_1__.Buffer.isBuffer(data)) {
    throw new TypeError("Expected \"string\" | \"Buffer\" | \"ArrayBuffer\" but received \"".concat(Object.prototype.toString.call(data), "\""));
  } 


  if (!REG_EXP_KEY.test(key)) {
    throw new TypeError('Invalid value of cipher `key`');
  }

  key = buffer__WEBPACK_IMPORTED_MODULE_1__.Buffer.from(key, 'hex'); // CBC 鍒嗙粍蹇呴』鍒跺畾 iv

  if (mode === CBC && !iv) {
    iv = '00000000000000000000000000000000';
  }

  if (mode === CBC && !REG_EXP_KEY.test(iv)) {
    throw new TypeError('Invalid value of `iv` option');
  }

  iv = mode === CBC ? buffer__WEBPACK_IMPORTED_MODULE_1__.Buffer.from(iv, 'hex') : null;
  return _encrypt(daa, key, iv, outputEncoding, padding);
};

  • 写回答

25条回答 默认 最新

  • 清水白石008 2024-08-07 13:19
    关注
    🕒下午好,题主!目前:🟢[在线]
    📢参考GPT-4o mini 模型、由清水白石008整理提供!
    📣今日诗号:白雪纷飞映山川,冬来江水寒如铁。
    

    要在 Python 中重现 JavaScript 中生成的 Antireplay-Token,您需要实现 JavaScript 中的逻辑,包括时间戳的生成、随机数的生成以及 SM4 加密。以下是一个逐步的指导,帮助您在 Python 中实现这一过程。

    1. 获取时间戳和随机数

    首先,您需要获取当前的时间戳,并生成一个随机数。JavaScript 中的 Date.now() 返回的是自1970年1月1日以来的毫秒数。

    2. 实现 SM4 加密

    由于 SM4 加密算法在 Python 中并不常见,您可以使用第三方库来实现。可以使用 pycryptodomegmssl 等库来实现 SM4 加密。

    3. 完整的 Python 实现

    以下是一个示例代码,展示如何在 Python 中实现上述逻辑:

    import time
    import random
    from Crypto.Cipher import AES
    from Crypto.Util.Padding import pad
    import binascii
    
    # SM4 加密实现
    class SM4:
        def __init__(self, key):
            self.key = key
    
        def encrypt(self, data):
            cipher = AES.new(self.key, AES.MODE_CBC, iv=b'\x00' * 16)
            padded_data = pad(data.encode('utf-8'), 16)
            encrypted = cipher.encrypt(padded_data)
            return binascii.hexlify(encrypted).decode('utf-8')
    
    def get_replay_token(back_time_offset, sm4_key):
        # 获取当前时间戳
        time_now = int(time.time() * 1000) - back_time_offset
        time_str = str(time_now)
    
        # 生成随机数
        random_num = str(random.randint(100000, 999999))  # 生成6位随机数
        random_str = time_str[-9:] + random_num
    
        # 生成待加密字符串
        str_to_encrypt = f"{random_str}|{time_str}"
    
        # SM4 加密
        sm4 = SM4(binascii.unhexlify(sm4_key))
        return sm4.encrypt(str_to_encrypt)
    
    # 示例使用
    back_time_offset = 0  # 根据实际情况设置
    sm4_key = '20141131201411312014113120141131'  # SM4 密钥
    
    token = get_replay_token(back_time_offset, sm4_key)
    print(f"生成的 Antireplay-Token: {token}")
    

    4. 注意事项

    • SM4 加密:在上面的代码中,我们使用了 AES 模式来模拟 SM4 加密。您需要找到一个支持 SM4 的库,或者使用 gmssl 库来实现 SM4 加密。
    • 时间偏移back_time_offset 需要根据您的实际情况进行设置,确保它与 JavaScript 中的 window.backTimeOffset 相匹配。
    • 随机数生成:确保随机数的生成逻辑与 JavaScript 中的逻辑一致。

    5. 发送请求

    一旦您生成了 Antireplay-Token,您可以使用 requests 库发送 HTTP 请求:

    import requests
    
    url = "http://example.com/api"  # 替换为实际的 URL
    headers = {
        "Antireplay-Token": token,
        # 其他必要的请求头
    }
    
    response = requests.get(url, headers=headers)
    print(response.text)
    

    6. 总结

    通过以上步骤,您可以在 Python 中重现 JavaScript 中生成 Antireplay-Token 的逻辑,并使用该令牌发送请求。确保在实现过程中仔细检查加密算法和参数,以确保与 JavaScript 的实现一致。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(24条)

报告相同问题?

问题事件

  • 系统已结题 8月16日
  • 已采纳回答 8月8日
  • 修改了问题 8月2日
  • 创建了问题 8月1日