Кодувати 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.