ToolHub
View All Posts

URL-codering uitgelegd: wat is percent-codering

Elke keer dat u op een link klikt, een formulier verzendt of een webadres intypt, behandelt uw browser URL-codering achter de schermen. Die cryptische reeksen procenttekens en hexadecimale getallen die u in URL's ziet, zijn niet willekeurig; ze vormen een zorgvuldig ontworpen mechanisme dat het internet betrouwbaar laat werken. Begrip van URL-codering is essentieel voor webontwikkelaars, API-ontwerpers en iedereen die met webtechnologieën werkt. Deze gids legt uit wat URL-codering is, waarom het bestaat, hoe het werkt en welke beveiligingsimplicaties u moet kennen.

Wat is URL-codering?

URL-codering, formeel bekend als percent-codering, is een mechanisme dat is gedefinieerd in RFC 3986 en tekens converteert naar een formaat dat veilig kan worden verzonden binnen een Uniform Resource Identifier (URI). De URL-specificatie staat slechts een subset van ASCII-tekens toe om direct in een URL te verschijnen. Elk teken buiten deze toegestane set moet worden gecodeerd als een procentteken ( % ) gevolgd door twee hexadecimale cijfers die de bytewaarde van het teken vertegenwoordigen.

< %3C , omdat de ASCII-code voor < 60 is, wat 3C in hexadecimaal is.

Waarom URL-codering noodzakelijk is

URL's hebben een specifieke syntaxis die bepaalde tekens als scheidingstekens gebruikt. Het vraagteken ? scheidt het pad van de querystring. Het ampersand-teken & scheidt queryparameters. Het gelijkteken = scheidt parameternamen van waarden. De schuine streep / scheidt padsegmenten. Als deze tekens in de verzonden gegevens voorkomen, zouden ze verkeerd worden geïnterpreteerd als URL-structuur in plaats van inhoud.

Bedenk wat er gebeurt wanneer een gebruiker zoekt naar "rock & roll" op een website. Zonder codering zou de URL er zo uitzien: /search?q=rock & roll . De browser zou de & interpreteren als een scheidingsteken voor queryparameters, waardoor de query wordt opgesplitst in twee parameters: q=rock en een tweede parameter met de naam roll zonder waarde. URL-codering lost dit op: /search?q=rock%20%26%20roll .

Hoe percent-codering werkt

Het coderingsproces volgt een eenvoudig algoritme dat is gedefinieerd door de URI-specificatie:

  1. Identificeer niet-gereserveerde tekens: De tekens A-Z , a-z , 0-9 , - , . , _ en ~ zijn niet-gereserveerd. Ze hoeven nooit te worden gecodeerd en kunnen direct in een URL verschijnen.
  2. Identificeer gereserveerde tekens: De tekens : , / , ? , # , [ , ] , @ , ! , $ , & , ' , ( , ) , * , + , , , ; en = zijn gereserveerd voor URL-syntaxis. Ze moeten worden gecodeerd wanneer ze als gegevens worden gebruikt in plaats van als scheidingstekens.
  3. Codeer al het andere: Elk teken dat niet in de niet-gereserveerde of gereserveerde set staat, moet percent-gecodeerd worden. Dit omvat spaties, besturingstekens, non-ASCII-tekens en elk teken buiten het ASCII-bereik.

Het coderingsproces voor non-ASCII-tekens

Non-ASCII-tekens (zoals letters met accenten, CJK-tekens en emoji) vereisen een extra stap. Eerst wordt het teken geconverteerd naar zijn UTF-8-bytereeks. Vervolgens wordt elke byte afzonderlijk percent-gecodeerd. Dit betekent dat een enkel teken meerdere percent-gecodeerde tripletten kan opleveren.

Het Euro-teken ( ) heeft bijvoorbeeld de UTF-8-bytereeks E2 82 AC . Bij URL-codering wordt het %E2%82%AC . Het Chinese teken voor "midden" ( 中 ) heeft de UTF-8-reeks E4 B8 AD , wat %E4%B8%AD oplevert . De emoji 😀 (grijnzend gezicht) heeft een 4-byte UTF-8-reeks, die codeert naar %F0%9F%98%80 .

Veelvoorkomende gecodeerde tekens

De volgende tabel toont de meest voorkomende URL-gecodeerde tekens:

TekenGecodeerdASCII-codeReden
Spatie%2032 (0x20)Niet toegestaan in URL's
!%2133 (0x21)Gereserveerd (sub-delim)
#%2335 (0x23)Gereserveerd (fragmentscheidingsteken)
$%2436 (0x24)Gereserveerd (sub-delim)
&%2638 (0x26)Gereserveerd (queryscheidingsteken)
'%2739 (0x27)Gereserveerd (sub-delim)
(%2840 (0x28)Gereserveerd (sub-delim)
)%2941 (0x29)Gereserveerd (sub-delim)
+%2B43 (0x2B)Gereserveerd (spatie in query)
,%2C44 (0x2C)Gereserveerd (sub-delim)
/%2F47 (0x2F)Gereserveerd (padscheidingsteken)
:%3A58 (0x3A)Gereserveerd (schemascheidingsteken)
;%3B59 (0x3B)Gereserveerd (parameterscheidingsteken)
=%3D61 (0x3D)Gereserveerd (waardescheidingsteken)
?%3F63 (0x3F)Gereserveerd (queryscheidingsteken)
@%4064 (0x40)Gereserveerd (authorityscheidingsteken)
[%5B91 (0x5B)Gereserveerd (IPv6-letterlijke)
]%5D93 (0x5D)Gereserveerd (IPv6-letterlijke)

URL-codering versus HTML-codering

URL-codering en HTML-entiteitscodering worden vaak verward, maar ze dienen volledig verschillende doeleinden en werken in verschillende contexten.

URL-codering

URL-codering converteert tekens naar %XX-formaat voor veilige verzending binnen een URL. Het valt onder RFC 3986 en wordt toegepast op URL-componenten zoals het pad, de querystring en het fragment.

HTML-codering

< en > voor veilige weergave binnen een HTML-document. Het voorkomt dat de browser inhoud interpreteert als HTML-markup. HTML-codering valt onder de HTML-specificatie.

Belangrijkste verschillen

AspectURL-coderingHTML-codering
ContextURL's en URI'sHTML-documenten
Formaat%XX (procent + hex)of &#NNN;
<%3C<
Voorbeeld voor &%26Voorbeeld voor "
%22"Doel
Veilige URL-transmissieHTML-injectie voorkomenSpecificatie
RFC 3986HTML Living Standard HTML Living Standard

(HTML-gecodeerd ampersand). Beide zijn geldig, maar URL-codering van het ampersand is de meer correcte benadering omdat het de beoogde betekenis van de gegevens behoudt.

URL-codering in verschillende programmeertalen

Elke grote programmeertaal biedt ingebouwde functies voor URL-codering en -decodering. Het exacte gedrag verschilt echter, en het begrijpen van de verschillen is cruciaal om bugs te voorkomen.

JavaScript

JavaScript biedt drie coderingsfuncties, elk met verschillend gedrag:

// 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

Het kritieke verschil is dat encodeURI URL-structuurtekens behoudt, terwijl encodeURIComponent alles codeert. Gebruik encodeURI wanneer u een volledige URL hebt en encodeURIComponent wanneer u een enkele parameterwaarde codeert.

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"

Het spatieteken: %20 versus +

Het spatieteken heeft twee veelvoorkomende coderingen, en het begrijpen van wanneer u welke moet gebruiken is belangrijk:

Het onderscheid is belangrijk omdat het decoderen van + als een spatie alleen correct is in de context van application/x-www-form-urlencoded-gegevens. In het URL-padcomponent is + een letterlijk plusteken, geen spatie. De meeste server-side frameworks behandelen dit correct voor querystrings, maar het kan subtiele bugs veroorzaken bij het coderen van paden of het werken met aangepaste URL-schema's.

Beveiligingsimplicaties

URL-codering heeft aanzienlijke beveiligingsimplicaties die elke webontwikkelaar moet begrijpen.

Dubbele coderingsaanvallen

Dubbele codering treedt op wanneer gegevens meer dan eens worden URL-gecodeerd. Een aanvaller zou %2527 kunnen indienen, wat bij de eerste decodeeringspassage %27 oplevert en bij de tweede passage een enkel aanhalingsteken ' . Als een beveiligingsfilter alleen de eerste decodering controleert, mist het het kwaadaardige teken. Dit kan invoervalidatie, cross-site scripting (XSS)-filters en SQL-injectiebescherming omzeilen.