Błędy w kodowaniu adresów URL wciąż popełniane przez programistów (i poprawki)

Błędy w kodowaniu adresów URL są subtelne, trwałe i często wykrywane w środowisku produkcyjnym. Źle umiejscowiony %20, podwójnie zakodowany ampersand lub zdezorientowany + vs space może przerwać wywołania API, uszkodzić dane śledzenia i stworzyć luki w zabezpieczeniach. Naprawmy te najczęstsze.
Przetestuj swoje kodowanie za pomocą naszego Koder/dekoder adresu URL narzędzie — wklej dowolny ciąg i natychmiast zobacz zakodowany wynik.
encodeURI vs encodeURIComponent
JavaScript ma dwie wbudowane funkcje kodowania, a użycie niewłaściwej jest głównym źródłem błędów:
| Funkcjonować | Koduje | Konserwuje | Użyj dla |
|---|---|---|---|
kodujURI | Spacje, inne niż ASCII | : /? # [ ] @! $ & ' ( ) * + , ; = | Kodowanie pełnego adresu URL |
koduj komponent URI | Wszystko powyżej +: /? #@! $ & ' ( ) * + , ; = | Tylko - _ . ~ i alfanumeryczne | Kodowanie wartości parametru zapytania |
// ŹLE — encodeURI zachowuje & w wartościach zapytania
const url = 'https://api.example.com/search?q=' + encodeURI('tom i jerry');
// Wynik: https://api.example.com/search?q=tom%20&%20jerry
// Znak & zostaje zachowany — teraz wygląda jak osobny parametr! // PRAWDA
const url = 'https://api.example.com/search?q=' + encodeURIComponent('tom i jerry');
// Wynik: https://api.example.com/search?q=tom%20%26%20jerry
Praktyczna zasada: Używać koduj komponent URI dla poszczególnych wartości. Używać kodujURI tylko wtedy, gdy masz pełny adres URL, który wymaga jedynie zakodowania znaków innych niż ASCII.
Błędy podwójnego kodowania
Podwójne kodowanie ma miejsce, gdy już zakodowany ciąg znaków jest ponownie kodowany:
const nazwa = 'witaj świecie';
const encoded = encodeURIComponent(nazwa); // witaj%20świecie
const doubled = encodeURIComponent (zakodowany); // witaj%2520świecie
// %25 to kodowanie samego %!
Zwykle ma to miejsce, gdy:
- Struktura automatycznie koduje parametry zapytania, a Ty także je wstępnie kodujesz
- Adres URL jest kodowany przed zapisaniem, a następnie kodowany ponownie po pobraniu
- Oprogramowanie pośredniczące przetwarza adres URL na wielu warstwach, z których każda dodaje kodowanie
Wykrywanie
Szukać %25 w adresach URL — prawie zawsze jest to oznaka podwójnego kodowania. Sekwencja %2520(podwójnie zakodowana spacja) to klasyczna wskazówka.
Zamieszanie + vs% 20
W przesyłanych formularzach HTML (application/x-www-form-urlencoded), przestrzenie stają się +. W standardowym kodowaniu procentowym (RFC 3986) spacje stają się %20.
To ma znaczenie, ponieważ:
dekoduj komponent URIrobi nie rozszyfrować+z powrotem w przestrzeń – pozostawia ją jako dosłowną+- Struktury zaplecza mogą, ale nie muszą, być automatycznie dekodowane
+w zależności od parsera - Jeśli Twój interfejs API tego oczekuje
%20ale otrzymuje+, wyszukuje hasło „czerwony+samochód” i zwraca wyniki w postaci „czerwony+samochód” (z dosłownym plusem) zamiast „czerwony samochód”
// Bezpieczne dekodowanie obsługujące + i %20
funkcja SafeDecodeParam(wartość) { zwróć decodeURIComponent(value.replace(/\+/g, '%20'));
} Obudowy krawędziowe UTF-8
Znaki inne niż ASCII, takie jak é, ü, 日本語, a emoji muszą być zakodowane procentowo jako sekwencje bajtów UTF-8:
encodeURIComponent('kawiarnia') // caf%C3%A9
encodeURIComponent('日本語') // %E6%97%A5%E6%9C%AC%E8%AA%9E
zakodujURIComponent('🔒') // %F0%9F%94%92
Problemy pojawiają się, gdy:
- Serwer oczekuje Latin-1, ale otrzymuje UTF-8 (mojibake — zniekształcone znaki)
- Kolumny bazy danych nie są ustawione na UTF-8, co dyskretnie obcina znaki wielobajtowe
- Pliki dziennika interpretują zakodowane ciągi znaków z nieprawidłowym zestawem znaków
Pułapki w adresach URL przekierowań i wywołań zwrotnych
Wywołania zwrotne OAuth i przekierowania są szczególnie podatne na błędy kodowania:
// Tworzenie przekierowania OAuth
const redirectUri = 'https://myapp.com/callback?source=oauth';
const authUrl = `https://provider.com/auth?redirect_uri=${encodeURIComponent(redirectUri)}`;
// Poprawnie: cały adres URL wywołania zwrotnego (w tym jego własny?) jest kodowany jako wartość pojedynczego parametru
Typowe błędy:
- Nie kodowanie
przekierowanie_uriw ogóle —?w wywołaniu zwrotnym dzieli nadrzędny adres URL - Kodowanie
przekierowanie_uriczęściowo — kodowanie ścieżki, ale nie zapytania - Kodowanie całego adresu URL uwierzytelniania zamiast tylko wartości parametru
Błędy te często tworzą luki w zabezpieczeniach związane z otwartym przekierowaniem, które napastnicy wykorzystują do phishingu.
Lista kontrolna debugowania
Jeśli adres URL nie działa zgodnie z oczekiwaniami, sprawdź kolejno:
- Poszukaj%25— oznacza podwójne kodowanie
- Sprawdź + vs%20— czy przestrzenie są obsługiwane w sposób spójny?
- Sprawdź surowe żądanie— użyj karty Sieć DevTools przeglądarki, aby zobaczyć faktycznie przesłany zakodowany adres URL
- Testuj ze znakami specjalnymi- próbować
& =? # /w wartościach, aby sprawdzić, czy naruszają one strukturę adresu URL - Sprawdź typ zawartości— czy serwer analizuje jako
application/x-www-form-urlencodedLubaplikacja/json? - Sprawdź dekodowanie na serwerze— rejestruj surowe i zdekodowane wartości po stronie serwera
Bezpieczne funkcje pomocnicze
// Bezpiecznie zbuduj ciąg zapytania
funkcja buildQueryString(parametry) { return Wpisy obiektu (parametry) .map(([klucz, wartość]) => `${encodeURIComponent(klucz)}=${encodeURIComponent(wartość)}` ) .dołącz('&');
} // Użyj URLSearchParams (nowoczesne przeglądarki + Node.js)
const params = new URLSearchParams({ q: 'tom i jerry', strona: '1' });
const url = `https://api.example.com/search?${params}`;
// Poprawnie: obsługuje kodowanie automatycznie
Najlepsza praktyka: Używać Parametry wyszukiwania URL Lub Adres URL konstruktor zamiast ręcznego łączenia ciągów. Domyślnie poprawnie obsługują kodowanie.
Często zadawane pytania
Dlaczego + staje się spacją?
Jest to dziedzictwo kodowania formularzy HTML (application/x-www-form-urlencoded), gdzie spacje są kodowane jako +. W standardowym kodowaniu procentowym (RFC 3986) spacje są %20. The + konwencja dotyczy tylko ciągów zapytań w przesyłanych formularzach, a nie segmentów ścieżek lub innych części adresu URL.
Jak poprawnie kodować zagnieżdżone adresy URL?
Używać koduj komponent URI na wewnętrznym adresie URL przed umieszczeniem go w parametrze zapytania zewnętrznego adresu URL. To koduje znaki takie jak :/? które w innym przypadku byłyby interpretowane jako część struktury zewnętrznego adresu URL.
Dlaczego podpisy psują się po zakodowaniu adresu URL?
Podpisy są obliczane na podstawie dokładnych sekwencji bajtów. Jeśli podpiszesz ciąg przed kodowaniem (lub po dekodowaniu), ale zweryfikujesz go w postaci zakodowanej (lub odwrotnie), bajty będą się różnić i podpis nie powiedzie się. Zawsze normalizuj kodowanie przed podpisaniem.
Powiązane narzędzia i artykuły
- Koder/dekoder adresu URL— testuj kodowanie w czasie rzeczywistym
- Błędy bezpieczeństwa JWT— kodowanie ma również znaczenie w przypadku obsługi tokenów
- Poprawka niedopasowania sumy kontrolnej— przy zmianach kodowania uszkodzone skróty plików