Как безопасно кодировать URL-адрес с помощью JavaScript, чтобы его можно было вставить в строку GET?

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

Я предполагаю, что вам нужно закодировать переменную myUrl во второй строке?

2434
nickf 2 Дек 2008 в 05:37

15 ответов

Лучший ответ

Ознакомьтесь со встроенной функцией encodeURIComponent (str) и encodeURI (str). < бр / > В вашем случае это должно работать:

var myOtherUrl = 
       "http://example.com/index.html?url=" + encodeURIComponent(myUrl);
2757
georgeawg 22 Апр 2019 в 07:02

Чтобы предотвратить двойное кодирование, рекомендуется декодировать URL-адрес перед кодированием (например, если вы имеете дело с введенными пользователем URL-адресами, которые могут быть уже закодированы).

Допустим, у нас есть abc%20xyz 123 в качестве входных данных (один пробел уже закодирован):

encodeURI("abc%20xyz 123")            //   wrong: "abc%2520xyz%20123"
encodeURI(decodeURI("abc%20xyz 123")) // correct: "abc%20xyz%20123"
4
serg 5 Янв 2017 в 18:49

Лучший ответ - использовать encodeURIComponent для values в строке запроса (и нигде больше).

Тем не менее, я считаю, что многие API хотят заменить "" на "+", поэтому мне пришлось использовать следующее:

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

escape реализован по-разному в разных браузерах, и encodeURI не кодирует много символов (например, # и даже /) - он предназначен для использования на полном URI / URL без его разбивки - что не так Это супер полезно или безопасно.

И, как указывает @Jochem ниже, вы можете использовать encodeURIComponent() для (каждого) имени папки, но по какой-то причине эти API, похоже, не хотят + в именах папок, столь старых {X2}} отлично работает.

Примере:

const escapedValue = encodeURIComponent(value).replace('%20','+');
const escapedFolder = encodeURIComponent('My Folder'); // no replace
const url = `http://example.com/${escapedFolder}/?myKey=${escapedValue}`;
82
Ryan Taylor 21 Авг 2019 в 16:11

Вы можете использовать библиотеку esapi и кодировать свой URL, используя функцию ниже. Функция гарантирует, что «/» не будут потеряны для кодирования, в то время как остальная часть текстового содержимого закодирована:

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
Mohith Maratt 17 Июл 2019 в 08:37

Для кодирования URL, как уже было сказано, у вас есть две функции:

encodeURI()

И

encodeURIComponent()

Причина обоих заключается в том, что первый сохраняет URL-адрес с риском оставить слишком много вещей без изменений, а второй кодирует все необходимое.

С первым вы можете скопировать недавно экранированный URL в адресную строку (например), и он будет работать. Однако ваши неэкранированные '& будут мешать разделителям полей,' = 'будут влиять на имена и значения полей, а' + 'будут выглядеть как пробелы. Но для простых данных, когда вы хотите сохранить природу URL того, что вы избегаете, это работает.

Второе - это все, что вам нужно сделать, чтобы ничто в вашей строке не мешало URL. Это оставляет различные неважные символы без экранирования, так что URL остается максимально удобным для чтения человеком без помех. URL, закодированный таким образом, больше не будет работать как URL без его удаления.

Поэтому, если вы можете потратить время, вы всегда хотите использовать encodeURIComponent () - перед добавлением пар имя / значение кодируйте и имя, и значение, используя эту функцию, перед добавлением его в строку запроса.

Мне трудно найти причины для использования encodeURI () - я оставлю это более умным людям.

10
Gerard ONeill 26 Янв 2017 в 21:31

Элегантный способ

По моему скромному мнению, самый элегантный способ кодирования параметров запроса - создать объект с такими параметрами, как

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

И затем закодируйте его, используя:

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

Как уже упоминалось в этом ответе: https://stackoverflow.com/a/53171438/7284582

1
Qback 9 Янв 2020 в 13:59

Если вы используете jQuery, я бы выбрал метод $.param. Он URL кодирует поля сопоставления объектов со значениями, которые легче читать, чем вызывать метод escape для каждого значения.

$.param({a:"1=2", b:"Test 1"}) // gets a=1%3D2&b=Test+1
40
Mark Amery 25 Май 2014 в 22:55

У меня ничего не получалось. Все, что я видел, это HTML-код страницы входа, возвращаясь на клиентскую сторону с кодом 200. (Сначала 302, но тот же Ajax-запрос, загружающий страницу входа в другой Ajax-запрос, который должен был быть перенаправлением, а не простой загрузкой текст страницы входа).

В контроллере входа я добавил эту строку:

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

И в глобальном обработчике Ajax я сделал это:

$(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;
            }
        }
    });
});

Теперь у меня нет никаких проблем, и это работает как шарм.

3
Peter Mortensen 3 Янв 2013 в 07:31

EncodeURIComponent () - это путь.

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

НО вы должны иметь в виду, что есть небольшие отличия от версии php urlencode(), и, как упоминалось в @CMS, он не будет кодировать каждый символ. Ребята из http://phpjs.org/functions/urlencode/ сделали js эквивалентом {{X1 } } :

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', '+');
}
11
Ryan Taylor 21 Авг 2019 в 16:21

Что такое кодировка URL:

URL-адрес должен быть закодирован, если в нем есть специальные символы. Например:

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

В этом примере мы можем наблюдать, что все символы, за исключением строки notEncoded, кодируются со знаками%. Кодировка URL также известна как процентная кодировка , поскольку она экранирует все специальные символы с помощью%. Затем после этого знака% каждый специальный символ имеет уникальный код

Зачем нам нужна кодировка URL:

Некоторые символы имеют специальное значение в строке URL. Например,? символ обозначает начало строки запроса. Чтобы успешно найти ресурс в сети, необходимо различать, когда символ подразумевается как часть строки или часть структуры URL.

Как мы можем добиться кодирования URL в JS:

JS предлагает набор встроенных служебных функций, которые мы можем использовать для простого кодирования URL. Это два удобных варианта:

  1. encodeURIComponent(): принимает компонент URI в качестве аргумента и возвращает закодированную строку URI.
  2. encodeURI(): принимает URI в качестве аргумента и возвращает закодированную строку URI.

Пример и предостережения:

Помните, что не нужно передавать весь URL (включая схему, например, https: //) в encodeURIComponent(). Это может фактически превратить его в не функциональный URL. Например:

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

Мы можем заметить, что если поместить весь URL-адрес в encodeURIComponent, то косая черта (/) также преобразуется в специальные символы. Это приведет к тому, что URL больше не будет работать должным образом.

Поэтому (как следует из названия) используйте:

  1. encodeURIComponent в определенной части URL, который вы хотите закодировать.
  2. encodeURI на весь URL, который вы хотите закодировать.
4
Willem van der Veen 23 Сен 2018 в 08:35

Кодировать строку URL

    var url = $(location).attr('href'); //get current url
    //OR
    var url = 'folder/index.html?param=#23dd&noob=yes'; //or specify one

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
Sangeet Shah 10 Сен 2015 в 06:41

У вас есть три варианта:

  • escape() не будет кодировать: @*/+

  • encodeURI() не будет кодировать: ~!@#$&*()=:/,;?+'

  • encodeURIComponent() не будет кодировать: ~!*()'

Но в вашем случае, если вы хотите передать URL в GET параметр на другой странице вы должны использовать escape или encodeURIComponent, но не encodeURI.

См. Вопрос переполнения стека Рекомендуемая практика: escape или encodeURI / encodeURIComponent для дальнейшего обсуждения.

1508
Community 23 Май 2017 в 12:02

Вот LIVE DEMO из {{X0} } и decodeURIComponent() встроенные функции JS:

<!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>
2
jonathana 9 Фев 2019 в 10:26

Используйте функцию fixedEncodeURIComponent, чтобы строго соблюдать RFC 3986:

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}
1
Arthur 5 Окт 2019 в 20:48

Подобные вещи я пробовал с обычным JavaScript

function fixedEncodeURIComponent(str){
     return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
}
5
2 revs, 2 users 89% 14 Май 2013 в 08:01