it-swarm-vi.com

Khi nào bạn nên sử dụng lối thoát thay vì encodeURI/encodeURIComponent?

Khi mã hóa chuỗi truy vấn được gửi đến máy chủ web - khi nào bạn sử dụng escape() và khi nào bạn sử dụng encodeURI() hoặc encodeURIComponent():

Sử dụng lối thoát:

escape("% +&=");

OR

sử dụng encodeURI ()/encodeURIComponent ()

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

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

bỏ trốn()

Đừng sử dụng nó! escape() được định nghĩa trong phần B.2.1.2 thoát và văn bản giới thiệu của Phụ lục B nói:

... Tất cả các tính năng và hành vi ngôn ngữ được chỉ định trong phụ lục này có một hoặc nhiều đặc điểm không mong muốn và trong trường hợp không sử dụng di sản sẽ bị xóa khỏi thông số kỹ thuật này. ...
... Các lập trình viên không nên sử dụng hoặc giả sử sự tồn tại của các tính năng và hành vi này khi viết mã ECMAScript mới ....

Hành vi:

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

Các ký tự đặc biệt được mã hóa ngoại trừ: @ * _ + -. /

Dạng thập lục phân cho các ký tự, có giá trị đơn vị mã là 0xFF trở xuống, là một chuỗi thoát hai chữ số: %xx.

Đối với các ký tự có đơn vị mã lớn hơn, định dạng bốn chữ số %uxxxx được sử dụng. Điều này không được phép trong chuỗi truy vấn (như được xác định trong RFC3986 ):

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

Dấu phần trăm chỉ được phép nếu nó được theo dõi trực tiếp bởi hai chữ số, phần trăm theo sau là u không được phép.

mã hóa ()

Sử dụng encodeURI khi bạn muốn một URL hoạt động. Thực hiện cuộc gọi này:

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

để có được:

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

Đừng gọi encodeURIComponent vì nó sẽ phá hủy URL và trả về

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

encodeURIComponent ()

Sử dụng encodeURIComponent khi bạn muốn mã hóa giá trị của tham số URL.

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

Sau đó, bạn có thể tạo URL bạn cần:

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

Và bạn sẽ nhận được URL hoàn chỉnh này:

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

Lưu ý rằng encodeURIComponent không thoát ký tự '. Một lỗi phổ biến là sử dụng nó để tạo các thuộc tính html như href='MyUrl', có thể bị lỗi tiêm. Nếu bạn đang xây dựng html từ các chuỗi, hãy sử dụng " thay vì ' cho dấu ngoặc kép thuộc tính hoặc thêm một lớp mã hóa bổ sung (' có thể được mã hóa thành% 27).

Để biết thêm thông tin về loại mã hóa này, bạn có thể kiểm tra: http://en.wikipedia.org/wiki/Percent-encoding

1847
Arne Evertsson

Sự khác biệt giữa encodeURI()encodeURIComponent() chính xác là 11 ký tự được mã hóa bởi encodeURIComponent nhưng không phải bởi encodeURI:

Table with the ten differences between encodeURI and encodeURIComponent

Tôi đã tạo bảng này dễ dàng với console.table trong Google Chrome với mã này:

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

411
Johann Echavarria

Tôi tìm thấy bài viết này khai sáng: Javascript Madness: Phân tích chuỗi truy vấn

Tôi đã tìm thấy nó khi tôi đang cố gắng nhấn mạnh tại sao giải mã không phải là giải mã chính xác '+'. Đây là một đoạn trích:

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!
43
Damien

encodeURIComponent không mã hóa -_.!~*'(), gây ra sự cố khi đăng dữ liệu lên php trong chuỗi xml.

Ví dụ:
<xml><text x="100" y="150" value="It's a value with single quote" /> </xml>

Lối thoát chung với 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

Bạn có thể thấy, trích dẫn đơn không được mã hóa . Để giải quyết vấn đề tôi đã tạo hai hàm để giải quyết vấn đề trong dự án của mình, cho Mã hóa 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");
}

Để giải mã 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 "";
}
38
Kirankumar Sripati

encodeURI () - hàm esc () dành cho thoát javascript, không phải HTTP.

37
Daniel Papasian

Bảng so sánh nhỏ Java so với JavaScript so với 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
16
30thh

Tôi khuyên bạn không nên sử dụng một trong những phương pháp đó. Viết chức năng của riêng bạn mà làm điều đúng.

MDN đã đưa ra một ví dụ tốt về mã hóa url được hiển thị bên dưới.

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

11
Jerry Joseph

Cũng nên nhớ rằng tất cả chúng đều mã hóa các bộ ký tự khác nhau và chọn bộ ký tự bạn cần một cách thích hợp. encodeURI () mã hóa ít ký tự hơn encodeURIComponent (), mã hóa ít hơn (và cũng khác nhau, theo điểm của dannyp) so với esc ().

10
Pseudo Masochist

Với mục đích mã hóa javascript đã đưa ra ba hàm sẵn có -

  1. esc () - không mã hóa @*/+ Phương thức này không được dùng sau ECMA 3 vì vậy cần tránh.

  2. encodeURI () - không mã hóa [email protected]#$&*()=:/,;?+' Nó giả sử rằng URI là một URI hoàn chỉnh, do đó không mã hóa các ký tự dành riêng có ý nghĩa đặc biệt trong URI . Phương thức này được sử dụng khi mục đích chuyển đổi hoàn thành URL thay vì một số phân đoạn đặc biệt của URL . Ví dụ - encodeURI('http://stackoverflow.com'); Sẽ cung cấp - http://stackoverflow.com

  3. encodeURIComponent () -không mã hóa - _ . ! ~ * ' ( ) Hàm này mã hóa thành phần Mã định danh tài nguyên thống nhất (URI) bằng cách thay thế từng phiên bản của một số ký tự nhất định bằng một, hai, ba hoặc bốn chuỗi thoát biểu thị mã hóa UTF-8 của ký tự. Phương pháp này nên được sử dụng để chuyển đổi một thành phần của URL. Chẳng hạn, một số đầu vào của người dùng cần được thêm vào Ví dụ - encodeURI('http://stackoverflow.com'); Sẽ cung cấp - http% 3A% 2F% 2Fstackoverflow.com

Tất cả mã hóa này được thực hiện trong UTF 8, tức là các ký tự sẽ được chuyển đổi ở định dạng UTF-8. 

encodeURIComponent khác với encodeURI ở chỗ nó mã hóa các ký tự dành riêng và ký hiệu số # của encodeURI

6
Gaurav Tiwari

Tôi đã phát hiện ra rằng thử nghiệm các phương pháp khác nhau là kiểm tra độ tỉnh táo ngay cả khi đã xử lý tốt những công dụng và khả năng khác nhau của chúng.

Tôi đã tìm thấy trang web này cực kỳ hữu ích để xác nhận những nghi ngờ của tôi rằng tôi đang làm một cái gì đó một cách thích hợp. Nó cũng đã được chứng minh là hữu ích cho việc giải mã một chuỗi mã hóa, có thể khá khó khăn để diễn giải. Một dấu trang tuyệt vời để có:

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

3
veeTrain

Tôi có chức năng này ...

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

Câu trả lời được chấp nhận là tốt . Để mở rộng về phần cuối cùng:

Lưu ý rằng encodeURIComponent không thoát khỏi ký tự '. Điểm chung lỗi là sử dụng nó để tạo các thuộc tính html như href = 'MyUrl', trong đó có thể bị lỗi tiêm. Nếu bạn đang xây dựng html từ các chuỗi, sử dụng "thay vì 'cho dấu ngoặc kép thuộc tính hoặc thêm lớp mã hóa bổ sung (' có thể được mã hóa thành% 27).

Nếu bạn muốn ở bên an toàn, phần trăm mã hóa các ký tự không được giám sát cũng nên được mã hóa. 

Bạn có thể sử dụng phương thức này để thoát chúng (nguồn Mozilla )

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

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

Viết lại hiện đại câu trả lời của @ 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
        )
)

Hoặc nếu bạn có thể sử dụng bảng, thay thế console.log bằng console.table (cho đầu ra đẹp hơn).

1
ryanpcmcquen

Lấy cảm hứng từ Bảng của Johann , tôi đã quyết định mở rộng bảng. Tôi muốn xem các ký tự ASCII được mã hóa.

 screenshot of console.table

var ascii = " !\"#$%&'()*+,-./0123456789:;<=>[email protected][\\]^_`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);

Bảng chỉ hiển thị các ký tự được mã hóa. Các ô trống có nghĩa là các ký tự gốc và ký tự được mã hóa giống nhau.


Chỉ để thêm, tôi đang thêm một bảng khác cho urlencode() vs rawurlencode() . Sự khác biệt duy nhất dường như là mã hóa ký tự không gian.

 screenshot of console.table

<script>
<?php
$ascii = str_split(" !\"#$%&'()*+,-./0123456789:;<=>[email protected][\\]^_`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>
0
akinuri