0

为什么 %e9 或 %fd 使用 Javascript 中的 decodeURIComponent 解码无效字符串?

这些字符出现在字符串的中间,我不明白问题出在哪里。它们是有效的十六进制字符。

完整字符串(这是客户端应用程序发送到服务器的字符串的一部分,并且被 modsec 阻止):

%61%e9%3d%36%7f%00%00%01%00%00%43%fd%a1%5a%00%00%00%43

解码样本:

decodeURIComponent("%61%e9%3d%36%7f%00%00%01%00%00%43%fd%a1%5a%00%00%00%43")

错误:

VM222:1 Uncaught URIError: URI malformed
    at decodeURIComponent (<anonymous>)
    at <anonymous>:1:1

我正在使用这两个函数来编码 base64 和从 base64 解码(来自这里:Mozilla):

function c64(t) {
        return btoa(encodeURIComponent(t).replace(/%([0-9A-F]{2})/g,
                (match, p1) => {
            return String.fromCharCode('0x' + p1);
        }));
    }

function d64(t) {
        return decodeURIComponent(atob(t).split('').map(function (c) {
            return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
        }).join(''));
    }

原始字符串在 base64 中:

d64("Yek9Nn8AAAEAAEP9oVoAAABDYek9Nn8AAAEAAEP9oVoAAABD")

返回:

...js:1 Uncaught URIError: URI malformed
    at decodeURIComponent (<anonymous>)
4

1 回答 1

0

这是因为该字符在十六进制编码中的 unicode 表示不是"%e9"or "%E9"

首先输入控制台: "\u00e9""\u00E9"

"\u00"在您的示例中被替换为 % 。你会得到:

'é'

您可以通过运行来验证这一点:

escape('é') //"%E9".

现在运行

encodeURIComponent('é')

你不会"%C3%A9"得到"%E9"。这是因为encodeURIComponent返回字节的十六进制转储。如果字符是 2 个字节,你会得到%xx%yy,如果是 3 个字节,你会得到%xx%yy%zz

试试这个"€&quot;。首先做:

escape("€&quot;)

,你会得到'%u20AC'或相同"\u20AC"

要获取其字节码的十六进制转储,请运行:

encodeURIComponent("€&quot;)你会得到'%E2%82%AC'

这个来自维基百科“UTF-8”文章的例子详细解释了如何'%E2%82%AC'计算。它是11100010 10000010 10101100.

于 2022-01-20T22:54:16.297 回答