簡體   English   中英

你什么時候應該使用escape而不是encodeURI / encodeURIComponent?

[英]When are you supposed to use escape instead of encodeURI / encodeURIComponent?

編碼要發送到 Web 服務器的查詢字符串時 - 何時使用escape()以及何時使用encodeURI()encodeURIComponent()

使用轉義:

escape("% +&=");

或者

使用 encodeURI() / encodeURIComponent()

encodeURI("http://www.google.com?var1=value1&var2=value2");

encodeURIComponent("var1=value1&var2=value2");

逃脫()

不要使用它! escape()在第B.2.1.2節中定義了轉義,附件 B介紹文本說:

... 本附件中指定的所有語言特性和行為都有一個或多個不受歡迎的特征,如果沒有遺留用法,將從本規范中刪除。 ...
...程序員在編寫新的 ECMAScript 代碼時不應使用或假設這些功能和行為的存在......

行為:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/escape

特殊字符編碼除外:@*_+-./

編碼單元值為 0xFF 或更小的字符的十六進制形式是一個兩位數的轉義序列: %xx

對於具有更大代碼單元的字符,使用四位格式%uxxxx 這在查詢字符串中是不允許的(如RFC3986 中所定義):

query       = *( pchar / "/" / "?" )
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded   = "%" HEXDIG HEXDIG
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
              / "*" / "+" / "," / ";" / "="

百分號只在后面直接跟兩個十六進制數字時才允許,百分比后面跟u是不允許的。

編碼URI()

當您需要工作 URL 時,請使用 encodeURI。 打這個電話:

encodeURI("http://www.example.org/a file with spaces.html")

要得到:

http://www.example.org/a%20file%20with%20spaces.html

不要調用 encodeURIComponent 因為它會破壞 URL 並返回

http%3A%2F%2Fwww.example.org%2Fa%20file%20with%20spaces.html

請注意,encodeURI 與 encodeURIComponent 一樣,不會對 ' 字符進行轉義。

編碼URI組件()

當您想要對 URL 參數的值進行編碼時,請使用 encodeURIComponent。

var p1 = encodeURIComponent("http://example.org/?a=12&b=55")

然后你可以創建你需要的 URL:

var url = "http://example.net/?param1=" + p1 + "&param2=99";

你會得到這個完整的 URL:

http://example.net/?param1=http%3A%2F%2Fexample.org%2F%Ffa%3D12%26b%3D55&param2=99

請注意, encodeURIComponent 不會對'字符進行轉義。 一個常見的錯誤是使用它來創建 html 屬性,例如href='MyUrl' ,這可能會遭受注入錯誤。 如果您從字符串構造 html,請使用"而不是'來表示屬性引號,或者添加額外的編碼層( '可以編碼為 %27)。

有關此類編碼的更多信息,您可以查看: http : //en.wikipedia.org/wiki/Percent-encoding

encodeURI()encodeURIComponent()之間的區別正好是由 encodeURIComponent 編碼而不是由 encodeURI 編碼的 11 個字符:

包含 encodeURI 和 encodeURIComponent 之間的十個差異的表

我使用以下代碼在谷歌瀏覽器中使用console.table輕松生成了這個表:

 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 Madness: Query String Parsing

當我試圖理解為什么 decodeURIComponent 沒有正確解碼“+”時,我發現了它。 這是一個摘錄:

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 不編碼-_.!~*'() ,導致在 xml 字符串中將數據發布到 php 時出現問題。

例如:
<xml><text x="100" y="150" value="It's a value with single quote" /> </xml>

使用encodeURI一般轉義
%3Cxml%3E%3Ctext%20x=%22100%22%20y=%22150%22%20value=%22It's%20a%20value%20with%20single%20quote%22%20/%3E%20%3C/xml%3E

你可以看到,單引號沒有被編碼。 為了解決問題,我創建了兩個函數來解決我的項目中的問題,用於編碼 URL:

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:

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 vs. JavaScript vs. PHP。

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 編碼。

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

為了編碼 javascript 給出了三個內置函數 -

  1. escape() - 不編碼@*/+此方法在 ECMA 3 之后被棄用,因此應避免使用。

  2. encodeURI() - 不編碼~!@#$&*()=:/,;?+'它假設 URI 是一個完整的 URI,所以不編碼在 URI 中具有特殊含義的保留字符。 當意圖是轉換完整的 URL 而不是 URL 的某些特殊段時,使用此方法。 示例 - encodeURI('http://stackoverflow.com'); 會給 - http://stackoverflow.com

  3. encodeURIComponent() - 不編碼- _ . ! ~ * ' ( ) - _ . ! ~ * ' ( ) - _ . ! ~ * ' ( )此函數通過用代表字符的 UTF-8 編碼的一個、兩個、三個或四個轉義序列替換特定字符的每個實例來對統一資源標識符 (URI) 組件進行編碼。 該方法應該用於轉換 URL 的組件。 例如,需要附加一些用戶輸入示例 - encodeURIComponent('http://stackoverflow.com'); 會給 - http%3A%2F%2Fstackoverflow.com

所有這些編碼都是在 UTF 8 中執行的,即字符將被轉換為 UTF-8 格式。

encodeURIComponent 與 encodeURI 的不同之處在於它對 encodeURI 的保留字符和數字符號 # 進行編碼

還要記住,它們都對不同的字符集進行編碼,並適當地選擇您需要的字符集。 encodeURI() 編碼的字符比 encodeURIComponent() 少,后者編碼的字符比escape() 少(而且也不同於 dannyp 的觀點)。

只需自己嘗試encodeURI()encodeURIComponent() ......

 console.log(encodeURIComponent('@#$%^&*'));

輸入: @#$%^&* 輸出: %40%23%24%25%5E%26* 那么,等等, *發生了什么? 為什么這個沒有轉換? 如果您嘗試執行linux command "$string"它肯定會導致問題。 TLDR:您實際上需要fixedEncodeURIComponent()fixedEncodeURI() 很長的故事...

何時使用encodeURI() 絕不。 encodeURI()在括號編碼方面未能遵守 RFC3986。 使用fixedEncodeURI() ,如MDN encodeURI() 文檔中定義和進一步解釋的那樣......

 function fixedEncodeURI(str) { return encodeURI(str).replace(/%5B/g, '[').replace(/%5D/g, ']'); }

何時使用encodeURIComponent() 絕不。 encodeURIComponent()在編碼方面未能遵守 RFC3986: !'()* 使用fixedEncodeURIComponent() ,如MDN encodeURIComponent() 文檔中定義和進一步解釋的那樣......

 function fixedEncodeURIComponent(str) { return encodeURIComponent(str).replace(/[!'()*]/g, function(c) { return '%' + c.charCodeAt(0).toString(16); }); }

然后您可以使用fixedEncodeURI()對單個 URL 片段進行編碼,而fixedEncodeURIComponent()將對 URL 片段和連接器進行編碼; 或者,簡單地說, fixedEncodeURI()不會編碼+@?=:#;,$& (因為&+是常見的 URL 運算符),但是fixedEncodeURIComponent()會。

我發現嘗試各種方法是一個很好的健全性檢查,即使在很好地掌握了它們的各種用途和功能之后也是如此。

為此,我發現這個網站非常有用,可以證實我對我正在做的事情的懷疑。 它也被證明對於解碼一個 encodeURIComponent 的字符串很有用,這對解釋來說可能相當具有挑戰性。 一個很棒的書簽:

http://www.the-art-of-web.com/javascript/escape/

接受的答案很好。 擴展最后一部分:

請注意, encodeURIComponent 不會轉義 ' 字符。 一個常見的錯誤是使用它來創建 html 屬性,例如 href='MyUrl',這可能會遭受注入錯誤。 如果您從字符串構造 html,請使用 " 而不是 ' 來表示屬性引號,或者添加額外的編碼層(' 可以編碼為 %27)。

如果您想安全起見,也應該對未保留字符的百分比編碼進行編碼。

您可以使用此方法來轉義它們(來源Mozilla

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}

// fixedEncodeURIComponent("'") --> "%27"

Johann 桌子的啟發,我決定擴展桌子。 我想看看哪些 ASCII 字符被編碼。

console.table 的屏幕截圖

 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);

表僅顯示編碼字符。 空單元格表示原始字符和編碼字符相同。


只是為了額外,我為urlencode()rawurlencode()添加了另一個表。 唯一的區別似乎是空格字符的編碼。

console.table 的屏幕截圖

<script>
<?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);
</script>

@johann-echavarria 答案的現代重寫:

 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 ) )

或者,如果您可以使用表格,請將console.log替換為console.table (以獲得更漂亮的輸出)。

我有這個功能...

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;
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM