Кодувати URL в JavaScript?


2469

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

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

Я припускаю, що вам потрібно кодувати myUrlзмінну у тому другому рядку?


22
Спробуйте переглянути encodeURI () та decodeURI () .
— Зак Людина


1
Ви можете скористатися цим інструментом тут: phillihp.com/toolz/url-encode-decode
— phillihp

2
encodeURIComponent ()
— Андрій

Відповіді:


2791

Перевірте вбудовану функцію encodeURIComponent (str) та encodeURI (str) .
У вашому випадку це має працювати:

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

12
Як щодо додавання пояснення @cms дав? escapeтакож є дійсним варіантом.
— hitautodestruct

11
згідно @CMS encodeURIне дуже безпечно для кодування URL-адрес.
— Ifnot

13
@AnaelFavre, оскільки він призначений для кодування всієї URL-адреси, яка не дозволяє такі символи, як :, /і @т. Д. Ці 2 методи не можна використовувати взаємозамінними, ви повинні знати, що ви кодуєте, щоб використовувати правильний метод.
— Buu Nguyen


Як уже згадувалося в іншій відповіді на цій сторінці , цей сайт чудово деталізує причину використання цього методу
— Brad Parks

1520

У вас є три варіанти:

  • escape() не кодує: @*/+

  • encodeURI() не кодує: ~!@#$&*()=:/,;?+'

  • encodeURIComponent() не кодує: ~!*()'

Але у вашому випадку, якщо ви хочете передати URL-адресу в GETпараметр іншої сторінки, ви повинні використовувати escapeабо encodeURIComponent, але ні encodeURI.

Див. Питання щодо переповнення стека. Найкраща практика: escape або encodeURI / encodeURIComponent для подальшого обговорення.


76
Кодування символів, що використовується при втечі, є змінною. Дотримуйтесь encodeURI та encodeURIComponent, які використовують UTF-8.
— erickson

6
Будь обережний. Це втеча перетворити не-ASCII символи в своїх керуючих послідовностей Unicode, як %uxxx.
— opteronn

4
Я використовую encodeURIComponent і помічаю, що він не кодує символи труби |
— kevzettler

15
@kevzettler - навіщо це робити? Труби не мають семантичного значення для URI.
— nickf

4
@GiovanniP: люди, які дозволяють вводити символи німецької, французької, японської, китайської, арабської мов та передавати параметри тези через GET або POST.
— Tseng

180

Дотримуйтесь encodeURIComponent(). Функція encodeURI()не заважає кодувати багато символів, які мають семантичне значення в URL-адресах (наприклад, "#", "?" Та "&").escape()застаріла і не переймається кодуванням символів "+", які будуть інтерпретуватися як закодовані пробіли на сервері (і, як вказують інші тут, не кодує URL-адреси, що не належать до ASCII).

Існує гарне пояснення різниці між encodeURI()іencodeURIComponent() в інших місцях. Якщо ви хочете щось кодувати так, щоб його можна було безпечно включати як компонент URI (наприклад, як параметр рядка запиту), який потрібно використовувати encodeURIComponent().


83

Найкращою відповіддю полягає у використанні encodeURIComponentна значеннях в рядку запиту (і ніде більше).

Однак я вважаю, що багато API хочуть замінити "" на "+", тому мені довелося використовувати наступне:

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

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

І як вказує @Jochem нижче, ви можете використовувати encodeURIComponent()ім'я папки (кожне), але з будь-якої причини ці API, схоже, не хочуть +у назвах папок, тому звичайний старий encodeURIComponentпрацює чудово.

Приклад:

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

22
Зауважте, ви повинні замінити% 20 символами + лише після першого знаку питання (який є частиною "запиту" URL-адреси). Скажімо, я хочу переглядати http://somedomain/this dir has spaces/info.php?a=this has also spaces. Його слід перетворити на: http://somedomain/this%20dir%20has%spaces/info.php?a=this%20has%20also%20spacesале багато реалізацій дозволяють "% 20" у рядку запитів замінити на "+". Тим не менш, ви не можете замінити "% 20" на "+" у розділі шляху URL-адреси, це призведе до помилки "Не знайдено", якщо у вас не буде каталогу +замість пробілу.
— Йохем Куджперс

@Jochem Kuijpers, безумовно, ви б не ставили "+" в каталог. Я застосував би це лише до самих значень параметрів запиту (або клавіш, якщо потрібно), а не до всієї URL-адреси чи навіть до всього рядка запиту.
— Райан Тейлор

Я б замінив у значенні, а не в результаті кодування
— njzk2

1
@ njzk2, на жаль encodeURIComponent('+'), дасть вам %2B, тож вам доведеться використовувати два регулярні вирази ... що, напевно, начебто чомусь це працює, тому що "+" є "кодуються по-різному.
— Райан Тейлор

Немає підстав перекладати% 20 на "+". Дійсна послідовність виходу для простору ASCII становить% 20, а не "+", що не згадується в RFC 3986 ( tools.ietf.org/html/rfc3986 ). "+" використовувався в 1990-х роках; вона застаріла і підтримується лише з застарілих причин. Не використовуйте його.
— xhienne

40

Якщо ви використовуєте jQuery, я б пішов на $.paramметод. Це URL-адреса кодує поля об’єктів, які відображають значення, що читається простіше, ніж виклик методу евакуації для кожного значення.

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

Я думаю, що наведеного прикладу достатньо. Якщо вам потрібна додаткова інформація про $ .param на api.jquery.com/jquery.param
— Максим Козленко

Майже всі користуються jQuery, і мені справді комфортно мені це робити замість encoreURIComponent
— Кирило Дюшон-Доріс

12

encodeURIComponent () - це шлях.

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

Але слід пам’ятати, що є невеликі відмінності від php-версії, urlencode()і як зазначалося @CMS, це не буде кодувати кожну таблицю. Хлопці з http://phpjs.org/functions/urlencode/ зробили js еквівалентним 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

Для кодування URL-адреси, як було сказано раніше, у вас є дві функції:

encodeURI()

і

encodeURIComponent()

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

По-перше, ви можете скопіювати щойно вийшов URL в адресний рядок (наприклад), і він буде працювати. Однак ваші незмінені 'і' будуть заважати роздільникам полів, '=' буде заважати іменам полів та значень, а '+' буде виглядати як пробіли. Але для простих даних, коли ви хочете зберегти характер URL-адреси того, до чого ви втекли, це працює.

Друге - це все, що вам потрібно зробити, щоб переконатися, що нічого в рядку не заважає URL-адресі. Залишає різні неважливі символи нерозміщеними, щоб URL залишався максимально зрозумілим для людей без втручання. Зашифрована таким чином URL-адреса більше не працюватиме як URL-адреса без її скасування.

Отже, якщо ви можете витратити час, ви завжди хочете використовувати encodeURIComponent () - перед тим, як додавати пари імен / значення, кодуйте і ім’я, і значення, використовуючи цю функцію, перш ніж додавати її до рядка запиту.

Мені важко придумувати причини використовувати encodeURI () - це я залишаю розумнішим людям.


5

Подібну річ я пробував із звичайним JavaScript

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

5

Елегантний спосіб

На мою скромну думку, найелегантніший спосіб кодування парамерів запитів - це створення об'єкта на зразок парам

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

а потім кодувати його за допомогою:

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

як згадується у цій відповіді: https://stackoverflow.com/a/53171438/7284582


4

Щоб запобігти подвійному кодуванню, корисно розшифрувати URL перед кодуванням (якщо, наприклад, ви маєте справу з введеними користувачем URL-адресами, які можуть бути вже закодовані).

Скажімо, у нас є abc%20xyz 123вхід (один пробіл вже закодовано):

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

4

Що таке кодування URL-адрес:

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-адресу, яку потрібно кодувати.

3

Ніщо не працювало для мене. Все, що я бачив, - це 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;
            }
        }
    });
});

Зараз у мене немає жодного питання, і це працює як шарм.


2

Кодування рядка URL-адреси

    var url = $ ( місцезнаходження ). attr ( 'href' ); // отримати поточний URL // АБО УАГ URL = 'Папка / index.html пари = # 23dd & нуб = так?' ; // або вказати один 
    
      

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

Ось ЖИВИЙ DEMO з encodeURIComponent()і 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>

1

Ви можете використовувати бібліотеку 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

Використовуйте fixedEncodeURIComponentфункцію, щоб суворо відповідати RFC 3986 :

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

1

Не слід використовувати encodeURIComponent()безпосередньо.

Погляньте на RFC3986: Уніфікований ідентифікатор ресурсу (URI): Загальний синтаксис

sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

Метою зарезервованих символів є надання набору символів, що розмежовують, які відрізняються від інших даних у URI.

Ці зарезервовані символи з визначення URI у RFC3986 НЕ уникнули encodeURIComponent().

Веб-документи MDN: encodeURIComponent ()

Щоб бути більш суворим у дотриманні RFC 3986 (який резервує!, ', (,) І *), хоча ці символи не мають формалізованого використання URI, що обмежує використання, можна безпечно використовувати наступне:

Використовуйте функцію MDN Web Docs ...

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.