【问题标题】:Python urllib.unquote_plus node.js equivalentPython urllib.unquote_plus node.js 等效
【发布时间】:2016-11-04 14:28:41
【问题描述】:

我正在尝试解码通过 HTTP GET 提供的一些数据,基本上是由 Python 编码的数据,我正在尝试使用 Node 对其进行解码。

Python

data = "0%0E%09-%FB%CD%989%2B%C0%E5%A2+%28%93%D9%C9%86r0%9C%8D+%F1%E3v%0C%9E%19%91%E3%06%01%FA%D5%5B%F3%3D7%10%23%E7%95S%B7%93%60%DB%1F%1F%8A%E3%5D%CC%95%B8%DA%DB%A3%18%9FoVzC%23%FCB%8D%86%86N9%BE%AE%98%13x%0D%D9u%C48%F6%AD%A3%19z%BE%DB%8E-%C4T%02P%06%D5%C1%21%1F%FB%9C%EB%0A%7C%F9XFB%9D%F3"
print urllib.unquote_plus(data)

输出:

0   -�͘9+�� (��Ɇr0�� ��v
�u�8�z�ێ-�TP��!��          �����[�=7#�S��`���]̕��ۣ�oVzC#�B���N9���x
|�XFB��

节点

var token = '0%0E%09-%FB%CD%989%2B%C0%E5%A2+%28%93%D9%C9%86r0%9C%8D+%F1%E3v%0C%9E%19%91%E3%06%01%FA%D5%5B%F3%3D7%10%23%E7%95S%B7%93%60%DB%1F%1F%8A%E3%5D%CC%95%B8%DA%DB%A3%18%9FoVzC%23%FCB%8D%86%86N9%BE%AE%98%13x%0D%D9u%C48%F6%AD%A3%19z%BE%DB%8E-%C4T%02P%06%D5%C1%21%1F%FB%9C%EB%0A%7C%F9XFB%9D%F3';
console.log(unescape(_.replace(token, '+', '%20')))

_ 是 Lodash 库。见https://lodash.com/docs/4.16.6#replace

输出:

0   -ûÍ9+Àå¢ (ÙÉr0+ñãv
ÙuÄ8ö­£z¾Û-ÄTPÕÁ!ûë          ãúÕ[ó=7#çS·`Ûã]̸ÚÛ£oVzC#üBN9¾®x
|ùXFBó

两个解码后的输出看起来很相似,但又有些不同,我不知道为什么。一旦解密(通过另一种算法),它们会给出类似的结果,但 JS 版本有意想不到的字符,如 {"duration": 600m�B�}PO�UQ��:...}',我不知道 JS 实现有什么问题。

【问题讨论】:

  • python 数据看起来已经损坏了。那应该代表什么? ͘ 表示字符集解码错误,因此它几乎不是预期的结果。另外,JS unescape() 函数已经被弃用很多年了,不要用它来做任何事情。
  • 它看起来坏了,因为它是使用 AES 256 CBC 加密的字符串,使用填充。但这只是(据我了解)因为结果是二进制数据,然后使用quote_plus 对其进行编码。当我使用 Python 解码和解密这个字符串时,它工作正常。但解码后的值确实看起来很奇怪。
  • 啊,我明白了。解码为字符串的任意二进制值看起来像这样。
  • 顺便说一句,通常人们会使用 Base64 以字符串形式传输二进制数据。将其直接编码为百分比编码并不理想。如果可以,请重新考虑值编码方法。
  • 不是我的电话,这是客户的实施。但请注意,谢谢 ;)

标签: javascript python node.js encoding urllib


【解决方案1】:

我不确定这是否以前做过(可能有,也许我没有正确搜索)。

您似乎需要一个函数,该函数将具有百分比编码的字符串解码为字节缓冲区,而不是像常规 URL 解码函数那样尝试执行的字符串。

function bufferUrlDecode(data) {
    var buf = new Buffer(data, 'ascii');
    var pos = 0, flag = false, prev = null, i, b;

    for (i = 0; i < buf.length; i++) {
        b = buf[i];
        if (flag) {
            b -= b < 58 ? 48 : b < 97 ? 55 : 87;  // hex char to half-byte value
            if (b < 0 || b > 15) {
                throw new Error('invalid encoding at position ' + i);
            } else if (prev === null) {
                prev = b << 4;
            } else {
                buf[pos++] = prev + b;
                flag = false;
                prev = null;
            }
        } else {
            if (b === 43 /* '+' becomes space */) {
                buf[pos++] = 32;
            } else if (b === 37 /* '%' triggers URL decoding */) {
                flag = true;
            } else {
                buf[pos++] = b;
            }
        }
    }

    if (prev !== null) throw new Error('invalid encoding at position ' + data.length);
    return buf.slice(0, pos);
}

用法:

var str = "0%0E%09-%FB%CD%989%2B%C0%E5%A2+%28%93%D9%C9%86r0%9C%8D+%F1%E3v%0C%9E%19%91%E3%06%01%FA%D5%5B%F3%3D7%10%23%E7%95S%B7%93%60%DB%1F%1F%8A%E3%5D%CC%95%B8%DA%DB%A3%18%9FoVzC%23%FCB%8D%86%86N9%BE%AE%98%13x%0D%D9u%C48%F6%AD%A3%19z%BE%DB%8E-%C4T%02P%06%D5%C1%21%1F%FB%9C%EB%0A%7C%F9XFB%9D%F3";    
var bytes = bufferUrlDecode(str);
console.log(bytes);
console.log(bytes.toString('hex'));

输出:

<Buffer 30 0e 09 2d fb cd 98 39 2b c0 e5 a2 20 28 ... >
300e092dfbcd98392bc0e5a22028 etc...

【讨论】:

  • 我认为这不适用于我的用例,因为解密 AES-256-CBC 算法(即使作为字符串)也无法使用缓冲区。我目前在尝试时得到Error: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length。我正在寻找的是在节点中正确实现urrllib.unquote_plus。我尝试混合unescapereplace,但我错过了一些东西。
  • 嗯。 crypto 模块中的方法与缓冲区一起使用,所以我不确定您所说的“缓冲区将不可用”是什么意思?我的实现中有一个愚蠢的错误。再试一次。
  • @Vadorequest 我的函数提供了正确的输出。没有您可以提供的反馈吗?
  • 我正要再试一次。我会给你一个反馈:)
  • @Vadorequest 我制作了一个改进的版本,它的运行速度明显加快(一个数量级)并且具有错误检查功能。
猜你喜欢
  • 2020-10-22
  • 2012-02-05
  • 1970-01-01
  • 2011-10-12
  • 2016-08-23
  • 1970-01-01
  • 1970-01-01
  • 2021-12-30
  • 1970-01-01
相关资源
最近更新 更多