Mã hóa URL trong JavaScript?


2470

Làm thế nào để bạn mã hóa URL một cách an toàn bằng JavaScript để có thể đưa nó vào chuỗi GET?

var myUrl = "http://example.com/index.html?param=1&anotherParam=2";
var myOtherUrl = "http://example.com/index.html?url=" + myUrl;

Tôi giả sử rằng bạn cần mã hóa myUrlbiến trên dòng thứ hai?


22
Hãy thử nhìn vào encodeURI ()decodeURI () .
Zack The Human


1
Bạn có thể sử dụng công cụ này tại đây: phillihp.com/toolz/url-encode-decode
phillihp

2
encodeURIComponent ()
Andrew

Câu trả lời:


2791

Kiểm tra hàm tích hợp encodeURIComponent (str)encodeURI (str) .
Trong trường hợp của bạn, điều này sẽ làm việc:

var myOtherUrl = 
       "http://example.com/index.html?url=" + encodeURIComponent(myUrl);

12
Làm thế nào về việc thêm lời giải thích @cms đã đưa ra? escapecũng là một lựa chọn hợp lệ.
hitautodesturation

11
theo @CMS encodeURIkhông thực sự an toàn cho mã hóa URL.
Ifnot

13
@AnaelFavre vì nó có nghĩa là để mã hóa toàn bộ URL, mà không cho phép nhân vật như :, /, @vv Những 2 phương pháp này không được sử dụng thay thế cho nhau, bạn phải biết những gì bạn đang mã hóa để sử dụng phương pháp đúng.
Bửu Nguyễn


Như đã đề cập trong một câu trả lời khác trên trang này , trang web này nêu chi tiết lý do để sử dụng phương pháp này
Brad park

1522

Bạn có ba lựa chọn:

  • escape() sẽ không mã hóa: @*/+

  • encodeURI() sẽ không mã hóa: ~!@#$&*()=:/,;?+'

  • encodeURIComponent() sẽ không mã hóa: ~!*()'

Nhưng trong trường hợp của bạn, nếu bạn muốn chuyển URL vào một GETtham số của trang khác, bạn nên sử dụng escapehoặc encodeURIComponentkhông encodeURI.

Xem câu hỏi Stack Overflow Thực hành tốt nhất: thoát hoặc mã hóa / mã hóa thành phần để thảo luận thêm.


76
Mã hóa ký tự được sử dụng với thoát là biến. Gắn bó với encodeURI và encodeURIComponent, sử dụng UTF-8.
erickson

6
Hãy cẩn thận. Lối thoát đó chuyển đổi các ký tự không phải ASCII thành các chuỗi thoát Unicode, như thế %uxxx.
opteronn

4
Tôi đang sử dụng encodeURIComponent và nhận thấy nó sẽ không mã hóa các ký tự ống |
kevzettler

15
@kevzettler - Tại sao nó phải làm vậy? Các ống không có tầm quan trọng về ngữ nghĩa trong một URI.
nickf

4
@GiovanniP: Những người cho phép các ký tự tiếng Đức, tiếng Pháp, tiếng Nhật, tiếng Trung, tiếng Ả Rập làm đầu vào và chuyển các tham số luận đề thông qua GET hoặc POST.
Tseng

180

Gắn bó với encodeURIComponent(). Hàm encodeURI()không bận tâm mã hóa nhiều ký tự có tầm quan trọng ngữ nghĩa trong các URL (ví dụ: "#", "?" Và "&"). escape()không được dùng nữa và không bận tâm mã hóa các ký tự "+", sẽ được hiểu là các khoảng trắng được mã hóa trên máy chủ (và, như được chỉ ra bởi những người khác ở đây, không mã hóa các ký tự không phải mã ASCII).

Có một lời giải thíchencodeURI()encodeURIComponent() tốt đẹp về sự khác biệt giữa nơi khác. Nếu bạn muốn mã hóa một cái gì đó để nó có thể được bao gồm một cách an toàn như là một thành phần của URI (ví dụ như tham số chuỗi truy vấn), bạn muốn sử dụng encodeURIComponent().


83

Câu trả lời tốt nhất là sử dụng encodeURIComponenttrên các giá trị trong chuỗi truy vấn (và không ở đâu khác).

Tuy nhiên, tôi thấy rằng nhiều API muốn thay thế "" bằng "+" vì vậy tôi đã phải sử dụng như sau:

const value = encodeURIComponent(value).replace('%20','+');
const url = 'http://example.com?lang=en&key=' + value

escapeđược triển khai khác nhau trong các trình duyệt khác nhau và encodeURIkhông mã hóa nhiều ký tự (như # và thậm chí /) - nó được tạo để sử dụng trên URI / URL đầy đủ mà không phá vỡ nó - điều này không hữu ích hoặc an toàn.

Và như @Jochem chỉ ra bên dưới, bạn có thể muốn sử dụng encodeURIComponent()tên thư mục (mỗi), nhưng vì bất kỳ lý do gì, các API này dường như không muốn +trong tên thư mục rất đơn giản encodeURIComponent.

Thí dụ:

const escapedValue = encodeURIComponent(value).replace('%20','+');
const escapedFolder = encodeURIComponent('My Folder'); // no replace
const url = `http://example.com/${escapedFolder}/?myKey=${escapedValue}`;

22
Xin lưu ý, bạn chỉ nên thay thế% 20 bằng các ký hiệu + sau dấu chấm hỏi đầu tiên (là phần 'truy vấn' của URL). Hãy nói rằng tôi muốn duyệt đến http://somedomain/this dir has spaces/info.php?a=this has also spaces. Nó nên được chuyển đổi thành: http://somedomain/this%20dir%20has%spaces/info.php?a=this%20has%20also%20spacesnhưng nhiều triển khai cho phép '% 20' trong chuỗi truy vấn được thay thế bằng '+'. Tuy nhiên, bạn không thể thay thế '% 20' bằng '+' trong phần đường dẫn của URL, điều này sẽ dẫn đến lỗi Không tìm thấy trừ khi bạn có một thư mục +thay vì khoảng trắng.
Joool Kuijpers

@Jochem Kuijpers, chắc chắn, bạn sẽ không đặt "+" trong một thư mục. Tôi chỉ áp dụng điều này cho chính các giá trị tham số truy vấn (hoặc khóa nếu cần), không phải toàn bộ URL hoặc thậm chí toàn bộ chuỗi truy vấn.
Ryan Taylor

Tôi sẽ thay thế bằng giá trị thay vì kết quả của mã hóa
njzk2

1
@ njzk2 không may encodeURIComponent('+')sẽ cung cấp cho bạn %2B, vì vậy bạn phải sử dụng hai biểu thức chính quy ... mà tôi cho là khá hợp lý tại sao điều này hoạt động, vì cuối cùng '+' là '' được mã hóa khác nhau.
Ryan Taylor

Không có lý do để dịch% 20 thành "+". Chuỗi thoát hợp lệ cho không gian ASCII là% 20, không phải "+" không được đề cập trong RFC 3986 ( tools.ietf.org/html/rfc3986 ). "+" được sử dụng vào những năm 1990; bây giờ nó đã lỗi thời và chỉ được hỗ trợ vì lý do di sản. Đừng sử dụng nó.
xhienne

40

Nếu bạn đang sử dụng jQuery, tôi sẽ dùng $.paramphương thức này. URL của nó mã hóa các trường ánh xạ đối tượng thành các giá trị, dễ đọc hơn là gọi một phương thức thoát trên mỗi giá trị.

$.param({a:"1=2", b:"Test 1"}) // gets a=1%3D2&b=Test+1

Tôi nghĩ rằng ví dụ được cung cấp là đủ. Nếu bạn cần thêm thông tin về $ .param
Maksym Kozlenko

Hầu như tất cả mọi người sử dụng jQuery và tôi thực sự cảm thấy thoải mái hơn với điều này thay vì encoreURIComponent
Cyril Duchon-Doris

12

encodeURIComponent () là cách để đi.

var myOtherUrl = "http://example.com/index.html?url=" + encodeURIComponent(myUrl);

NHƯNG bạn nên nhớ rằng có một số khác biệt nhỏ so với phiên bản php urlencode()và như @CMS đã đề cập, nó sẽ không mã hóa mọi char. Các chàng trai tại http://phpjs.org/fifts/urlencode/ đã tạo js tương đương với phpencode():

function urlencode(str) {
  str = (str + '').toString();

  // Tilde should be allowed unescaped in future versions of PHP (as reflected below), but if you want to reflect current
  // PHP behavior, you would need to add ".replace(/~/g, '%7E');" to the following.
  return encodeURIComponent(str)
    .replace('!', '%21')
    .replace('\'', '%27')
    .replace('(', '%28')
    .replace(')', '%29')
    .replace('*', '%2A')
    .replace('%20', '+');
}

10

Để mã hóa một URL, như đã nói trước đây, bạn có hai chức năng:

encodeURI()

encodeURIComponent()

Lý do cả hai tồn tại là cái đầu tiên bảo tồn URL với nguy cơ để lại quá nhiều thứ không được giải thoát, trong khi cái thứ hai mã hóa mọi thứ cần thiết.

Với lần đầu tiên, bạn có thể sao chép URL mới thoát vào thanh địa chỉ (ví dụ) và nó sẽ hoạt động. Tuy nhiên, '&' của bạn sẽ không can thiệp vào các dấu phân cách trường, '=' sẽ can thiệp vào tên và giá trị của trường và '+' sẽ trông giống như khoảng trắng. Nhưng đối với dữ liệu đơn giản khi bạn muốn duy trì bản chất URL của những gì bạn đang thoát, điều này hoạt động.

Thứ hai là mọi thứ bạn cần làm để đảm bảo không có gì trong chuỗi của bạn can thiệp vào một URL. Nó để các ký tự không quan trọng khác nhau không bị hủy bỏ để URL vẫn có thể đọc được ở người mà không bị can thiệp. Một URL được mã hóa theo cách này sẽ không còn hoạt động như một URL mà không bỏ qua nó.

Vì vậy, nếu bạn có thể dành thời gian, bạn luôn muốn sử dụng encodeURIComponent () - trước khi thêm các cặp tên / giá trị mã hóa cả tên và giá trị bằng hàm này trước khi thêm nó vào chuỗi truy vấn.

Tôi đang có một thời gian khó khăn để đưa ra lý do để sử dụng encodeURI () - Tôi sẽ để điều đó cho những người thông minh hơn.


5

Điều tương tự tôi đã thử với javascript bình thường

function fixedEncodeURIComponent(str){
     return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
}

5

Cách thanh lịch

Theo ý kiến ​​khiêm tốn của tôi, cách thanh lịch nhất để mã hóa các tham số truy vấn là tạo một đối tượng với các thông số như

const queryParams = { param1: 'value1', param2: 'value2' }

và sau đó mã hóa nó bằng cách sử dụng:

const queryString = new URLSearchParams(queryParams).toString()

như đã đề cập trong câu trả lời này: https://stackoverflow.com/a/53171438/7284582


4

Để ngăn chặn mã hóa kép, bạn nên giải mã url trước khi mã hóa (ví dụ: nếu bạn đang giao dịch với người dùng đã nhập url, có thể đã được mã hóa).

Hãy nói rằng chúng ta có abc%20xyz 123đầu vào (một không gian đã được mã hóa):

encodeURI("abc%20xyz 123")            //   wrong: "abc%2520xyz%20123"
encodeURI(decodeURI("abc%20xyz 123")) // correct: "abc%20xyz%20123"

4

Mã hóa URL là gì:

Một URL nên được mã hóa khi có các ký tự đặc biệt nằm trong URL. Ví dụ:

console.log(encodeURIComponent('?notEncoded=&+'));

Chúng ta có thể quan sát trong ví dụ này rằng tất cả các ký tự ngoại trừ chuỗi notEncodedđược mã hóa bằng dấu%. Mã hóa URL còn được gọi là mã hóa tỷ lệ phần trăm vì nó thoát khỏi tất cả các ký tự đặc biệt với%. Sau đó,% ký này, mỗi ký tự đặc biệt có một mã duy nhất

Tại sao chúng ta cần mã hóa URL:

Một số ký tự có giá trị đặc biệt trong chuỗi URL. Ví dụ: ký tự biểu thị sự bắt đầu của một chuỗi truy vấn. Để thành công xác định vị trí một tài nguyên trên web, cần phân biệt giữa khi nào một ký tự có nghĩa là một phần của chuỗi hoặc một phần của cấu trúc url.

Làm cách nào chúng ta có thể đạt được mã hóa URL trong JS:

JS cung cấp một loạt các hàm xây dựng trong chức năng tiện ích mà chúng ta có thể sử dụng để dễ dàng mã hóa URL. Đây là hai tùy chọn thuận tiện:

  1. encodeURIComponent(): Lấy một thành phần của URI làm đối số và trả về chuỗi URI được mã hóa.
  2. encodeURI(): Lấy URI làm đối số và trả về chuỗi URI được mã hóa.

Ví dụ và hãy cẩn thận:

Lưu ý rằng không chuyển toàn bộ URL (bao gồm cả lược đồ, ví dụ https: //) vào encodeURIComponent(). Điều này thực sự có thể chuyển đổi nó thành một URL không chức năng. Ví dụ:

// for a whole URI don't use encodeURIComponent it will transform
// the / characters and the URL won't fucntion properly
console.log(encodeURIComponent("http://www.random.com/specials&char.html"));

// instead use encodeURI for whole URL's
console.log(encodeURI("http://www.random.com/specials&char.html"));

Chúng tôi có thể quan sát f chúng tôi đặt toàn bộ URL trong encodeURIComponentđó các dấu gạch chéo (/) cũng được chuyển đổi thành các ký tự đặc biệt. Điều này sẽ khiến URL không hoạt động đúng nữa.

Do đó (như tên ngụ ý) sử dụng:

  1. encodeURIComponent trên một phần nhất định của URL mà bạn muốn mã hóa.
  2. encodeURI trên toàn bộ URL mà bạn muốn mã hóa.

3

Không có gì làm việc cho tôi. Tất cả những gì tôi thấy là HTML của trang đăng nhập, quay lại phía máy khách với mã 200. (Lúc đầu 302 nhưng cùng một yêu cầu Ajax tải trang đăng nhập bên trong một yêu cầu Ajax khác, được cho là chuyển hướng thay vì tải đơn giản văn bản của trang đăng nhập).

Trong trình điều khiển đăng nhập, tôi đã thêm dòng này:

Response.Headers["land"] = "login";

Và trong trình xử lý Ajax toàn cầu, tôi đã làm điều này:

$(function () {
    var $document = $(document);
    $document.ajaxSuccess(function (e, response, request) {
        var land = response.getResponseHeader('land');
        var redrUrl = '/login?ReturnUrl=' + encodeURIComponent(window.location);
        if(land) {
            if (land.toString() === 'login') {
                window.location = redrUrl;
            }
        }
    });
});

Bây giờ tôi không có bất kỳ vấn đề nào, và nó hoạt động như một cơ duyên.


2

Mã hóa chuỗi URL

    var url = $ ( vị trí ). attr ( 'href' ); // lấy url hiện tại // HOẶC var url = 'thư mục / index.html? param = # 23dd & noob = yes' ; // hoặc chỉ định một 
    
      

var encodedUrl = encodeURIComponent(url); console.log(encodedUrl); //outputs folder%2Findex.html%3Fparam%3D%2323dd%26noob%3Dyes for more info go http://www.sitepoint.com/jquery-decode-url-string

2

Đây là một DEMO WEBCAM của encodeURIComponent()decodeURIComponent()JS xây dựng trong các chức năng:

<!DOCTYPE html>
<html>
  <head>
    <style>
      textarea{
        width:30%;
        height:100px;
      }
    </style>
    <script>
      // encode string to base64
      function encode()
      {
        var txt = document.getElementById("txt1").value;
        var result = btoa(txt);
        document.getElementById("txt2").value = result;
      }
      // decode base64 back to original string
      function decode()
      {
        var txt = document.getElementById("txt3").value;
        var result = atob(txt);
        document.getElementById("txt4").value = result;
      }
    </script>
  </head>
  <body>
    <div>
      <textarea id="txt1">Some text to decode
      </textarea>
    </div>
    <div>
      <input type="button" id="btnencode" value="Encode" onClick="encode()"/>
    </div>
    <div>
      <textarea id="txt2">
      </textarea>
    </div>
    <br/>
    <div>
      <textarea id="txt3">U29tZSB0ZXh0IHRvIGRlY29kZQ==
      </textarea>
    </div>
    <div>
      <input type="button" id="btndecode" value="Decode" onClick="decode()"/>
    </div>
    <div>
      <textarea id="txt4">
      </textarea>
    </div>
  </body>
</html>

1

Bạn có thể sử dụng thư viện esapi và mã hóa url của mình bằng chức năng bên dưới. Hàm đảm bảo rằng '/' không bị mất khi mã hóa trong khi phần còn lại của nội dung văn bản được mã hóa:

function encodeUrl(url)
{
    String arr[] = url.split("/");
    String encodedUrl = "";
    for(int i = 0; i<arr.length; i++)
    {
        encodedUrl = encodedUrl + ESAPI.encoder().encodeForHTML(ESAPI.encoder().encodeForURL(arr[i]));
        if(i<arr.length-1) encodedUrl = encodedUrl + "/";
    }
    return url;
}

https://www.owasp.org/index.php/ESAPI_JavaScript_Readme


1

Sử dụng fixedEncodeURIComponentchức năng để tuân thủ nghiêm ngặt RFC 3986 :

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

1

Bạn không nên sử dụng encodeURIComponent()trực tiếp.

Hãy xem RFC3986: Mã định danh tài nguyên đồng nhất (URI): Cú pháp chung

phân định phụ = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

Mục đích của các ký tự dành riêng là cung cấp một tập hợp các ký tự phân cách có thể phân biệt với các dữ liệu khác trong URI.

Các ký tự dành riêng từ định nghĩa URI trong RFC3986 KHÔNG được thoát bởi encodeURIComponent().

Tài liệu web MDN: encodeURIComponent ()

Để nghiêm ngặt hơn trong việc tuân thủ RFC 3986 (dự trữ !, ', (,) Và *), mặc dù các ký tự này không có cách sử dụng phân định URI chính thức, có thể sử dụng một cách an toàn:

Sử dụng chức năng Tài liệu web MDN ...

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.