为什么 %fd 是 url 解码的无效字符串?
Why is %fd an invalid string for url decoding?
为什么使用 Javascript 中的 decodeURIComponent 解码 %e9 或 %fd 无效字符串?
这些字符出现在字符串的中间,我无法理解问题出在哪里。它们是有效的十六进制字符。
完整字符串(这是客户端应用程序发送到服务器的字符串的一部分,被 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")
returns:
...js:1 Uncaught URIError: URI malformed
at decodeURIComponent (<anonymous>)
这是因为该字符在十六进制编码中的 unicode 表示不是 "%e9"
或 "%E9"
。
首先在控制台中输入:
"\u00e9"
或 "\u00E9"
在您的示例中被 "\u00"
替换为 %。您将获得:
'é'
您可以通过 运行ning 验证:
escape('é') //"%E9".
现在运行
encodeURIComponent('é')
你会得到 "%C3%A9"
而不是 "%E9"
。这是因为 encodeURIComponent
returns 字节的十六进制转储。如果字符是 2 个字节,你得到 %xx%yy
,如果是 3 个字节,你得到 %xx%yy%zz
.
用 "€"
试试这个。首先做:
escape("€")
,你将得到 '%u20AC'
或与 "\u20AC"
相同。
获取其字节码的十六进制转储运行:
encodeURIComponent("€")
你会得到 '%E2%82%AC'
.
This example from Wikipedia 'UTF-8' article详细解释了'%E2%82%AC'
是如何计算的。它是 11100010 10000010 10101100
.
的十六进制转储
为什么使用 Javascript 中的 decodeURIComponent 解码 %e9 或 %fd 无效字符串?
这些字符出现在字符串的中间,我无法理解问题出在哪里。它们是有效的十六进制字符。
完整字符串(这是客户端应用程序发送到服务器的字符串的一部分,被 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")
returns:
...js:1 Uncaught URIError: URI malformed
at decodeURIComponent (<anonymous>)
这是因为该字符在十六进制编码中的 unicode 表示不是 "%e9"
或 "%E9"
。
首先在控制台中输入:
"\u00e9"
或 "\u00E9"
在您的示例中被 "\u00"
替换为 %。您将获得:
'é'
您可以通过 运行ning 验证:
escape('é') //"%E9".
现在运行
encodeURIComponent('é')
你会得到 "%C3%A9"
而不是 "%E9"
。这是因为 encodeURIComponent
returns 字节的十六进制转储。如果字符是 2 个字节,你得到 %xx%yy
,如果是 3 个字节,你得到 %xx%yy%zz
.
用 "€"
试试这个。首先做:
escape("€")
,你将得到 '%u20AC'
或与 "\u20AC"
相同。
获取其字节码的十六进制转储运行:
encodeURIComponent("€")
你会得到 '%E2%82%AC'
.
This example from Wikipedia 'UTF-8' article详细解释了'%E2%82%AC'
是如何计算的。它是 11100010 10000010 10101100
.