When are you supposed to use escape instead of encodeURI / encodeURIComponent?
当对发送到Web服务器的查询字符串进行编码时-您何时使用
使用逃逸:
1 | escape("% +&="); |
或
使用encodeuri()/encodeuricomponent())
1 2 3 | encodeURI("http://www.google.com?var1=value1&var2=value2"); encodeURIComponent("var1=value1&var2=value2"); |
逃逸()
不要使用它!
... All of the language features and behaviours specified in this annex have one or more undesirable characteristics and in the absence of legacy usage would be removed from this specification. ...
... Programmers should not use or assume the existence of these features and behaviours when writing new ECMAScript code....
Behaviour:
https://developer.mozilla.org/en-us/docs/web/javascript/reference/global_objects/escape
特殊字符编码,但:@*.-.除外。/
字符的十六进制形式,其代码单位值为0xff或更小,是一个两位数的转义序列:
对于代码单位较大的字符,使用四位格式
1 2 3 4 5 6 | query = *( pchar /"/" /"?" ) pchar = unreserved / pct-encoded / sub-delims /":" /"@" unreserved = ALPHA / DIGIT /"-" /"." /"_" /"~" pct-encoded ="%" HEXDIG HEXDIG sub-delims ="!" /"$" /"&" /"'" /"(" /")" /"*" /"+" /"," /";" /"=" |
只有在百分号后面直接跟两个十六进制数字时才允许使用百分号,不允许使用百分号后面跟
当需要工作的URL时,请使用encodeuri。打这个电话:
1 | encodeURI("http://www.example.org/a file with spaces.html") |
得到:
1 | http://www.example.org/a%20file%20with%20spaces.html |
不要调用encodeuricomponent,因为它会破坏URL并返回
1 | http%3A%2F%2Fwww.example.org%2Fa%20file%20with%20spaces.html |
编码成分()
要对URL参数的值进行编码时,请使用encodeuricomponent。
4然后您可以创建所需的URL:
1 | var url ="http://example.net/?param1=" + p1 +"¶m2=99"; |
你会得到这个完整的网址:
注意,编码成分不能逃逸
有关此类编码的详细信息,请查看:http://en.wikipedia.org/wiki/percent-encoding
我用Google Chrome中的console.table轻松生成了这个表,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 | var arr = []; for(var i=0;i<256;i++) { var char=String.fromCharCode(i); if(encodeURI(char)!==encodeURIComponent(char)) { arr.push({ character:char, encodeURI:encodeURI(char), encodeURIComponent:encodeURIComponent(char) }); } } console.table(arr); |
我发现这篇文章很有启发性:javascript疯狂:查询字符串解析
当我试图理解为什么解码组件没有正确解码"+"时,我发现了它。以下是摘录:
1 2 3 4 5 6 7 8 9 10 11 | String: "A + B" Expected Query String Encoding:"A+%2B+B" escape("A + B") = "A%20+%20B" Wrong! encodeURI("A + B") = "A%20+%20B" Wrong! encodeURIComponent("A + B") = "A%20%2B%20B" Acceptable, but strange Encoded String: "A+%2B+B" Expected Decoding: "A + B" unescape("A+%2B+B") = "A+++B" Wrong! decodeURI("A+%2B+B") = "A+++B" Wrong! decodeURIComponent("A+%2B+B") ="A+++B" Wrong! |
encodeuricomponent不编码
例如:
带
可以看到,单引号没有编码。为了解决问题,我创建了两个函数来解决项目中的问题,用于编码URL:
1 2 3 | function encodeData(s:String):String{ return encodeURIComponent(s).replace(/\-/g,"%2D").replace(/\_/g,"%5F").replace(/\./g,"%2E").replace(/\!/g,"%21").replace(/\~/g,"%7E").replace(/\*/g,"%2A").replace(/\'/g,"%27").replace(/\(/g,"%28").replace(/\)/g,"%29"); } |
对于解码URL:
1 2 3 4 5 6 7 | function decodeData(s:String):String{ try{ return decodeURIComponent(s.replace(/\%2D/g,"-").replace(/\%5F/g,"_").replace(/\%2E/g,".").replace(/\%21/g,"!").replace(/\%7E/g,"~").replace(/\%2A/g,"*").replace(/\%27/g,"'").replace(/\%28/g,"(").replace(/\%29/g,")")); }catch (e:Error) { } return""; } |
encodeuri()-escape()函数用于JavaScript转义,而不是HTTP。
小型比较表JAVA与JavaScript与PHP。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 1. Java URLEncoder.encode (using UTF8 charset) 2. JavaScript encodeURIComponent 3. JavaScript escape 4. PHP urlencode 5. PHP rawurlencode char JAVA JavaScript --PHP--- [ ] + %20 %20 + %20 [!] %21 ! %21 %21 %21 [*] * * * %2A %2A ['] %27 ' %27 %27 %27 [(] %28 ( %28 %28 %28 [)] %29 ) %29 %29 %29 [;] %3B %3B %3B %3B %3B [:] %3A %3A %3A %3A %3A [@] %40 %40 @ %40 %40 [&] %26 %26 %26 %26 %26 [=] %3D %3D %3D %3D %3D [+] %2B %2B + %2B %2B [$] %24 %24 %24 %24 %24 [,] %2C %2C %2C %2C %2C [/] %2F %2F / %2F %2F [?] %3F %3F %3F %3F %3F [#] %23 %23 %23 %23 %23 [[] %5B %5B %5B %5B %5B []] %5D %5D %5D %5D %5D ---------------------------------------- [~] %7E ~ %7E %7E ~ [-] - - - - - [_] _ _ _ _ _ [%] %25 %25 %25 %25 %25 [\] %5C %5C %5C %5C %5C ---------------------------------------- char -JAVA- --JavaScript-- -----PHP------ [?] %C3%A4 %C3%A4 %E4 %C3%A4 %C3%A4 [ф] %D1%84 %D1%84 %u0444 %D1%84 %D1%84 |
我建议不要使用这些方法中的一种。写出你自己的函数,它能做正确的事情。
MDN给出了一个很好的URL编码示例,如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | var fileName = 'my file(2).txt'; var header ="Content-Disposition: attachment; filename*=UTF-8''" + encodeRFC5987ValueChars(fileName); console.log(header); // logs"Content-Disposition: attachment; filename*=UTF-8''my%20file%282%29.txt" function encodeRFC5987ValueChars (str) { return encodeURIComponent(str). // Note that although RFC3986 reserves"!", RFC5987 does not, // so we do not need to escape it replace(/['()]/g, escape). // i.e., %27 %28 %29 replace(/\*/g, '%2A'). // The following are not required for percent-encoding per RFC5987, // so we can allow for a little better readability over the wire: |`^ replace(/%(?:7C|60|5E)/g, unescape); } |
https://developer.mozilla.org/en-us/docs/web/javascript/reference/global_objects/encodeuricomponent
还要记住,它们都对不同的字符集进行编码,并适当地选择所需的字符集。encodeUri()编码的字符数少于encodeUriComponent(),后者比escape()编码的字符数更少(也不同于dannyp的点)。
为了编码,javascript提供了三个内置函数-
escape()-不编码
encodeuri()-不编码
encodeuricomponent()-不编码
所有这些编码都是以UTF 8执行的,即字符将以UTF-8格式转换。
encodeuricomponent与encodeuri的不同之处在于,它对encodeuri的保留字符和数字符号进行编码。
我发现,即使在掌握了各种方法的各种用途和功能之后,使用各种方法进行试验也是一种良好的健全性检查。
为此,我发现这个网站非常有用,以证实我的怀疑,我正在做适当的事情。它也被证明有助于解码一个编码组成的字符串,这可能是相当困难的解释。一个很好的书签:
http://www.the-art-of-web.com/javascript/escape/
受约翰桌子的启发,我决定扩大桌子。我想看看哪些ASCII字符被编码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | var ascii =" !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; var encoded = []; ascii.split("").forEach(function (char) { var obj = { char }; if (char != encodeURI(char)) obj.encodeURI = encodeURI(char); if (char != encodeURIComponent(char)) obj.encodeURIComponent = encodeURIComponent(char); if (obj.encodeURI || obj.encodeURIComponent) encoded.push(obj); }); console.table(encoded); |
表仅显示编码字符。空单元格表示原始字符和编码字符相同。
另外,我要为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php $ascii = str_split(" !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", 1); $encoded = []; foreach ($ascii as $char) { $obj = ["char" => $char]; if ($char != urlencode($char)) $obj["urlencode"] = urlencode($char); if ($char != rawurlencode($char)) $obj["rawurlencode"] = rawurlencode($char); if (isset($obj["rawurlencode"]) || isset($obj["rawurlencode"])) $encoded[] = $obj; } echo"var encoded =" . json_encode($encoded) .";"; ?> console.table(encoded); |
现代改写@johann echavaria的答案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | console.log( Array(256) .fill() .map((ignore, i) => String.fromCharCode(i)) .filter( (char) => encodeURI(char) !== encodeURIComponent(char) ? { character: char, encodeURI: encodeURI(char), encodeURIComponent: encodeURIComponent(char) } : false ) ) |
或者,如果可以使用表,则将
公认的答案是好的。在最后一部分进行扩展:
Note that encodeURIComponent does not escape the ' character. A common
bug is to use it to create html attributes such as href='MyUrl', which
could suffer an injection bug. If you are constructing html from
strings, either use" instead of ' for attribute quotes, or add an
extra layer of encoding (' can be encoded as %27).
如果您希望在安全方面,也应该对未保留字符的百分比编码进行编码。
您可以使用此方法来转义它们(源代码mozilla)
1 2 3 4 5 6 7 | function fixedEncodeURIComponent(str) { return encodeURIComponent(str).replace(/[!'()*]/g, function(c) { return '%' + c.charCodeAt(0).toString(16); }); } // fixedEncodeURIComponent("'") -->"%27" |
我有这个功能…
1 2 3 4 5 6 7 | var escapeURIparam = function(url) { if (encodeURIComponent) url = encodeURIComponent(url); else if (encodeURI) url = encodeURI(url); else url = escape(url); url = url.replace(/\+/g, '%2B'); // Force the replacement of"+" return url; }; |