/ / RFC3986 - ktoré pchars musia byť percentuálne kódované? - java, jazyk-agnostik, rfc, rfc3986

RFC3986 - ktoré znaky musia byť percentuálne kódované? - java, jazykovo-agnostická, rfc, rfc3986

Potrebujem generovať href na URI. Všetko jednoduché, s výnimkou, keď ide o vyhradené znaky, ktoré vyžadujú percentuálne kódovanie, napr. odkaz na /some/path;element by sa malo zobraziť ako <a href="/some/path%3Belement"> (Viem že path;element predstavuje jednu entitu).

Spočiatku som hľadal knižnicu Java, ktorá to robí, ale nakoniec som niečo napísal sám (pozrite sa, čo sa nepodarilo v Jave, pretože táto otázka nie je špecifická pre Javu).

Takže, RFC 3986 navrhuje, kedy NESMIE kódovať. Toto by sa malo stať, ako som to čítal, keď postava spadne unreserved (ALPHA / DIGIT / "-" / "." / "_" / "~") trieda. Zatiaľ je všetko dobré. Čo však v opačnom prípade? RFC uvádza iba toto percento (%) vždy vyžaduje kódovanie. Ale čo ostatní?

Otázka: je správne predpokladať, že všetko, čo nie je vyhradené, môže / malo by byť kódované percentuálne? Napríklad otváracia konzola ( nemusí nutne vyžadovať kódovanie, ale bodkočiarku ; robí. Ak to nekódujem, nakoniec hľadám /first* pri sledovaní <a href="/first;second">. Ale nasledovanie <a href="/first(second"> Vždy skončím hľadaním /first(second, podľa očakávania. Mätie ma, že obaja ( a ; sú v tom istom sub-delims triedy pokiaľ ide o RFC. Ako si predstavujem, kódovanie všetkého bez výhrad je bezpečná stávka, ale čo SEOability a užívateľskej prívetivosti, pokiaľ ide o lokalizované URI?

Čo sa nepodarilo s Java libs. Skúšal som to robiť ako
new java.net.URI("http", "site", "/pa;th", null).toASCIISTring()
ale to dáva http://site/pa;th čo nie je dobré. Podobné výsledky pozorované u:

  • javax.ws.rs.core.UriBuilder
  • Jarné UriUtils - Skúšal som oboje encodePath(String, String) a encodePathSegment(String, String)

[*] /first je výsledkom volania na číslo HttpServletRequest.getServletPath() na strane servera po kliknutí na <a href="/first;second">

EDIT: Pravdepodobne musím spomenúť, že toto správanie bolo pozorované v Tomcat, a skontroloval som, že Tomcat 6 aj 7 sa správajú rovnako.

odpovede:

3 pre odpoveď č. 1

Je správne predpokladať, že všetko, čo nie je vyhradené, môže / malo by byť kódované percentuálne?

RFC 3986 hovorí toto:

„Za normálnych okolností jediný krát, keďoktety v rámci URI sú percentuálne kódované počas procesu výroby URI z jeho komponentov. To je prípad, keď implementácia určí, ktoré z vyhradených znakov sa majú použiť ako oddeľovače podzložiek a ktoré možno bezpečne použiť ako údaje. „

Z toho vyplýva, že vy rozhodujete, ktorý z oddeľovačov (t. J <delimiter> znakov) je potrebné kódovať v závislosti od kontextu. Tie, ktoré nie je potrebné kódovať, by sa nemali kódovať.

Napríklad by ste nemali percentuálne kódovať a / ak sa objaví v komponente cesty, ale mali by ste ho percentuálne zakódovať, keď sa objaví v dotaze alebo fragmente.

Takže v skutočnosti a ; znak (ktorý je členom <reserved> by nemali byť automaticky percentuálne kódované. A triedy Java URL a URI to skutočne neurobia; viď URI (...) javadoc, konkrétne krok 7), ako <path> komponentom je manipulované.

To podporuje tento odsek:

„Účelom vyhradených znakov je poskytnúťmnožina oddeľovacích znakov, ktoré sú odlíšiteľné od ostatných údajov v rámci URI. Identifikátory URI, ktoré sa líšia nahradením rezervovaného znaku zodpovedajúcim oktetom kódovaným v percentách, nie sú ekvivalentné. Percento kódovania vyhradeného znaku alebo dekódovanie percenta kódovaného oktetu, ktoré zodpovedá rezervovanému znaku, zmení spôsob interpretácie URI vo väčšine aplikácií. Znaky vo vyhradenej množine sú teda chránené pred normalizáciou, a preto je bezpečné ich použitie v algoritmoch špecifických pre určitú schému a pre producenta na vymedzenie dátových komponentov v rámci URI. “

Toto teda hovorí, že adresa URL obsahuje percentuálny kód ; nie je to isté ako adresa URL, ktorá obsahuje raw ;. A posledná veta znamená, že by nemali byť automaticky kódované alebo dekódované na percentá.


Čo nám ponecháva otázku - prečo vy chcieť ; byť percentuálne zakódovaný?

Povedzme, že máte CMS, kde môžu ľudia vytváraťľubovoľné stránky s ľubovoľnými cestami. Neskôr musím vygenerovať href odkazy na všetky stránky, napríklad v komponente mapa stránok. Preto potrebujem algoritmus, aby som vedel, ktorým znakom uniknúť. S bodkočiarkou sa v tomto prípade musí zaobchádzať doslovne a malo by sa jej uniknúť.

Ospravedlňujeme sa, ale z toho nevyplýva, že bodkočiarka by mala byť uniknutá.

Pokiaľ ide o špecifikáciu URL / URI, ; nemá žiadny zvláštny význam. Pre konkrétny webový server / webovú stránku to môže mať zvláštny význam, ale všeobecne (t. j. bez konkrétnych znalostí o stránke) to nemáte ako vedieť.

  • Ak ; má v konkrétnom URI špeciálny význam, potom ak percentuálnym spôsobom uniknete, tento význam zlomíte. Napríklad ak web používa ; Ak chcete povoliť pripojenie tokenu relácie k ceste, potom percentuálne kódovanie zabráni rozpoznaniu tokenu relácie ...

  • Ak ; je jednoducho dátový znak poskytovaný niektorýmiklient, potom ak ho percentuálne zakódujete, potenciálne zmeníte význam URI. Či to záleží, závisí od toho, čo server robí; tj či je alebo nie je súčasťou logiky aplikácie.

Čo to znamená poznať „správnu vec“vyžaduje dôkladnú znalosť toho, čo URI znamená pre koncového používateľa a / alebo web. To by si vyžadovalo implementáciu pokročilej technológie čítania myšlienok. Moje odporúčanie by bolo dostať CMS, aby to vyriešil vhodným únikom z akýchkoľvek oddeľovačov ciest URI pred dodáva ich do vášho softvéru. Algoritmus je nutne bude špecifický pre CMS a platformu na doručovanie obsahu. Bude / budú odpovedať na žiadosti o dokumenty identifikované pomocou adries URL a budú musieť vedieť, ako ich interpretovať.

(Podpora ľubovoľných ľudí pomocou ľubovoľných ciest je trochu šialená. Musí byť niektorí limity.Napríklad ani Windows vám neumožňujú použiť oddeľovač znakov v súbore názvu súboru. Takže niekde budete musieť mať nejaké hranice. Ide iba o rozhodnutie, kde by mali byť.)


1 pre odpoveď č. 2

Na ABNF pre časť absolútnej cesty:

 path-absolute = "/" [ segment-nz *( "/" segment ) ]
segment       = *pchar
segment-nz    = 1*pchar
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
pct-encoded   = "%" HEXDIG HEXDIG
unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
reserved      = gen-delims / sub-delims
sub-delims    = "!" / "$" / "&" / """ / "(" / ")"
/ "*" / "+" / "," / ";" / "="

pchar obsahuje podpoložky, aby ste nemuseli kódovať nič z toho v časti cesty: :@-._~!$&"()*+,;=

napísal som môj vlastný nástroj na tvorbu adries URL ktorý obsahuje kódovač cesty - ako vždy, výhrada emptor.