ToolHub
View All Posts

Kodowanie URL szczegółowo: Czym jest kodowanie procentowe

Za każdym razem, gdy klikasz link, wysyłasz formularz lub wpisujesz adres URL, Twoja przeglądarka obsługuje kodowanie URL w tle. Te tajemnicze ciągi znaków procentu i cyfr szesnastkowych, które widzisz w URL, nie są przypadkowe; to starannie zaprojektowany mechanizm, który sprawia, że internet działa niezawodnie. Zrozumienie kodowania URL jest kluczowe dla deweloperów webowych, projektantów API i wszystkich pracujących z technologiami webowymi. Ten przewodnik wyjaśnia, czym jest kodowanie URL, dlaczego istnieje, jak działa i jakie implikacje bezpieczeństwa musisz znać.

Czym jest kodowanie URL?

Kodowanie URL, formalnie nazywane kodowaniem procentowym, to mechanizm zdefiniowany w RFC 3986, który konwertuje znaki na format bezpieczny do transmisji w Uniform Resource Identifier (URI). Specyfikacja URL zezwala tylko na podzbiór znaków ASCII do bezpośredniego występowania w URL. Każdy znak spoza tego dozwolonego zestawu musi być zakodowany jako znak procenta (%) i dwie cyfry szesnastkowe reprezentujące wartość bajtową znaku.

< staje się %3C, ponieważ kod ASCII < to 60, co w zapisie szesnastkowym daje 3C.

Dlaczego kodowanie URL jest potrzebne

URL mają specyficzną składnię używającą niektórych znaków jako separatorów. Znak zapytania ? oddziela ścieżkę od stringa zapytania. Ampersand & oddziela parametry zapytania. Znak równości = oddziela nazwy parametrów od wartości. Ukośnik / oddziela segmenty ścieżki. Jeśli te znaki pojawiają się w przesyłanych danych, są błędnie interpretowane jako struktura URL, a nie treść.

Zastanów się, co się dzieje, gdy użytkownik szuka "rock & roll" na stronie. Bez kodowania URL byłby /search?q=rock & roll. Przeglądarka zinterpretuje & jako separator parametrów zapytania, dzieląc zapytanie na dwa parametry: q=rock i drugi parametr o nazwie roll (bez wartości). Kodowanie URL naprawia ten problem: /search?q=rock%20%26%20roll.

Jak działa kodowanie procentowe

Proces kodowania przebiega według prostego algorytmu zdefiniowanego przez specyfikację URI:

  1. Identyfikacja znaków niezastrzeżonych: Znaki A-Z, a-z, 0-9, -, ., _ i ~ są niezastrzeżone. Nigdy nie wymagają kodowania i mogą występować bezpośrednio w URL.
  2. Identyfikacja znaków zastrzeżonych: Znaki :, /, ?, #, [, ], @, !, $, &, ', (, ), *, +, ,, ; i = są zastrzeżone dla składni URL. Muszą być kodowane, gdy są używane jako dane, a nie jako separatory.
  3. Koduj wszystkie pozostałe znaki: Każdy znak spoza zbioru znaków niezastrzeżonych lub zastrzeżonych musi być kodowany procentowo. Obejmuje to spacje, znaki kontrolne, znaki spoza ASCII i wszelkie znaki spoza zakresu ASCII.

Proces kodowania znaków spoza ASCII

Znaki spoza ASCII (takie jak litery akcentowane, znaki CJK i emoji) wymagają dodatkowego kroku. Najpierw konwertuje się znak na jego sekwencję bajtów UTF-8. Następnie każdy bajt jest indywidualnie kodowany procentowo. Oznacza to, że pojedynczy znak może generować wiele trójek kodowania procentowego.

Na przykład znak euro (€) ma sekwencję bajtów UTF-8 E2 82 AC. Po zakodowaniu URL staje się %E2%82%AC. Przykładowy znak chiński ma sekwencję UTF-8 E4 B8 AD, dając %E4%B8%AD. Emoji 😀 (uśmiechnięta twarz) ma 4-bajtową sekwencję UTF-8 zakodowaną jako %F0%9F%98%80.

Popularne znaki kodowane

Poniższa tabela pokazuje najczęściej kodowane znaki URL:

znakówKodujKod ASCIIPrzyczyna
Spacja%2032 (0x20)Niedozwolone w URL
!%2133 (0x21)Zastrzeżony (subseparator)
#%2335 (0x23)Zastrzeżony (separator fragmentu)
$%2436 (0x24)Zastrzeżony (subseparator)
&%2638 (0x26)Zastrzeżony (separator zapytania)
'%2739 (0x27)Zastrzeżony (subseparator)
(%2840 (0x28)Zastrzeżony (subseparator)
)%2941 (0x29)Zastrzeżony (subseparator)
+%2B43 (0x2B)Zastrzeżony (spacja w zapytaniu)
,%2C44 (0x2C)Zastrzeżony (subseparator)
/%2F47 (0x2F)Zastrzeżony (separator ścieżki)
:%3A58 (0x3A)Zastrzeżony (separator schematu)
;%3B59 (0x3B)Zastrzeżony (separator parametrów)
=%3D61 (0x3D)Zastrzeżony (separator wartości)
?%3F63 (0x3F)Zastrzeżony (separator zapytania)
@%4064 (0x40)Zastrzeżony (separator autoryzacji)
[%5B91 (0x5B)Zastrzeżony (literał IPv6)
]%5D93 (0x5D)Zastrzeżony (literał IPv6)

Kodowanie URL a kodowanie HTML

Kodowanie URL i kodowanie encji HTML są często mylone, ale służą zupełnie innym celom i działają w różnych kontekstach.

Kodowanie URL

Kodowanie URL konwertuje znaki na format %XX w celu bezpiecznej transmisji w URL. Jest regulowane przez RFC 3986 i stosowane do komponentów URL, takich jak ścieżka, string zapytania i fragment.

Kodowanie HTML

Kodowanie HTML konwertuje znaki na odwołania encji, takie jak &, < i >, aby bezpiecznie renderować je w dokumencie HTML. Zapobiega to interpretowaniu treści przez przeglądarkę jako znaczniki HTML. Kodowanie HTML jest regulowane przez specyfikację HTML.

Kluczowa różnica

AspektKodowanie URLKodowanie HTML
KontekstURL i URIDokument HTML
Format%XX (procent + szesnastkowo)lub &#NNN;
<%3C<
przykład &%26" przykłady
%22"Cel
Bezpieczna transmisja URLZapobieganie HTML injectionSpecyfikacja
RFC 3986HTML Living Standard HTML Living Standard

(znak & zakodowany HTML). Oba są poprawne, ale kodowanie URL znaku & jest bardziej właściwym podejściem, ponieważ zachowuje zamierzone znaczenie danych.

Kodowanie URL w różnych językach programowania

Każdy główny język programowania oferuje wbudowane funkcje kodowania i dekodowania URL. Jednak dokładne zachowanie jest różne, a zrozumienie różnic jest kluczowe dla uniknięcia błędów.

JavaScript

JavaScript oferuje trzy funkcje kodowania, każda o innym zachowaniu:

// encodeURI - encodes a complete URL
// Preserves: :, /, ?, #, &, =, +, @, ;, ,, !, ~, *, ', (, )
const url = encodeURI("https://example.com/search?q=hello world");
// Result: "https://example.com/search?q=hello%20world"

// encodeURIComponent - encodes a URL component
// Encodes ALL special characters including URL delimiters
const param = encodeURIComponent("price=100&discount=20");
// Result: "price%3D100%26discount%3D20"

// Never use escape() - it is deprecated
// It does not handle Unicode correctly

Kluczowa różnica polega na tym, że encodeURI zachowuje znaki strukturalne URL, podczas gdy encodeURIComponent koduje wszystko. Używaj encodeURI, gdy masz pełny URL, a encodeURIComponent do kodowania pojedynczych wartości parametrów.

Python

from urllib.parse import quote, quote_plus, urlencode

# quote - standard URL encoding (spaces as %20)
encoded = quote("hello world&more")
# Result: "hello%20world%26more"

# quote_plus - spaces become + instead of %20
encoded_plus = quote_plus("hello world")
# Result: "hello+world"

# urlencode - encodes a dictionary as a query string
params = {"q": "hello world", "lang": "en"}
query = urlencode(params)
# Result: "q=hello+world&lang=en"

PHP

// urlencode - spaces become +
$encoded = urlencode("hello world&more");
// Result: "hello+world%26more"

// rawurlencode - RFC 3986 compliant (spaces as %20)
$raw = rawurlencode("hello world&more");
// Result: "hello%20world%26more"

Znak spacji: %20 vs +

Znak spacji ma dwa popularne kodowania i ważne jest zrozumienie, kiedy używać każdego z nich:

To rozróżnienie jest ważne, ponieważ dekodowanie + jako spacji jest poprawne tylko w kontekście danych application/x-www-form-urlencoded. W komponentach ścieżki URL + jest dosłownym znakiem plus, nie spacją. Większość frameworków serwerowych obsługuje to poprawnie dla ciągów zapytań, ale może prowadzić do subtelnych błędów podczas kodowania ścieżek lub korzystania z niestandardowych schematów URL.

Implikacje bezpieczeństwa

Kodowanie URL ma istotne implikacje bezpieczeństwa, które każdy programista webowy musi rozumieć.

Atak podwójnego kodowania

Podwójne kodowanie występuje, gdy dane są kodowane URL wielokrotnie. Atakujący może przesłać %2527, które po pierwszym dekodowaniu staje się %27, a po drugim dekodowaniu pojedynczym cudzysłowem '. Jeśli filtr bezpieczeństwa sprawdza tylko pierwsze dekodowanie, pomija złośliwy znak. Może to ominąć walidację wejścia, filtry Cross-Site Scripting (XSS) i ochronę przed SQL injection.