Czy koduję ampersandy w <a href…>?


157

Piszę kod, który automatycznie generuje HTML i chcę, aby kodował poprawnie.

Powiedzmy, że generuję łącze do następującego adresu URL:

http://www.google.com/search?rls=en&q=stack+overflow

Zakładam, że wszystkie wartości atrybutów powinny być zakodowane w formacie HTML. (Proszę poprawić mnie, jeśli się mylę.) Oznacza to, że jeśli umieszczam powyższy adres URL w tagu kotwicy, powinienem zakodować ampersand as &amp;, na przykład:

<a href="http://www.google.com/search?rls=en&amp;q=stack+overflow">

Czy to jest poprawne?



6
@CiroSantilli: chodzi o rzeczywiste ciągi adresów URL; chodzi o to, jak są one kodowane, gdy pojawiają się w atrybutach HTML.
JW.

jak widzę, kodowanie ampersandów nie zawsze jest wymagane w HTML5, a odpowiedzi są nieaktualne.
qdinar

Odpowiedzi:


175

Tak to jest. Jednostki HTML są analizowane wewnątrz atrybutów HTML, a zbłąkane elementy &spowodowałyby niejednoznaczność. Dlatego zawsze powinieneś pisać, &amp;a nie tylko &wewnątrz wszystkich atrybutów HTML.

To powiedziawszy, tylko &i cytaty muszą być zakodowane. Jeśli masz znaki specjalne, takie jak éw swoim atrybucie, nie musisz ich kodować, aby spełnić wymagania parsera HTML.

Kiedyś adresy URL wymagały specjalnego traktowania ze znakami spoza zestawu ASCII, na przykład é. Trzeba było zakodować te za pomocą znaków procentowych, aw tym przypadku dałoby to %C3%A9, ponieważ zostały zdefiniowane w RFC 1738 . Jednak RFC 1738 został zastąpiony przez RFC 3986 (URI, Uniform Resource Identifiers) i RFC 3987 (IRI, Internationalized Resource Identifiers), na których opiera swoją pracę WhatWG, aby zdefiniować, jak powinny zachowywać się przeglądarki, gdy widzą adres URL bez ASCII znaków w nim od HTML5 . Dlatego teraz można bezpiecznie umieszczać w adresach URL znaki spoza zestawu ASCII, zakodowane procentowo lub nie.


1
Byłem tego prawie pewien, ale miałem rzadką chwilę zwątpienia. Dziękuję za potwierdzenie.
JW.

1
Możesz także zakodować spacje jako „+” zamiast% 20 - co sprawia, że ​​adres URL jest łatwiejszy do odczytania.
NickG,

1
+ nie jest obecnie szanowany w linkach mailto w natywnym kliencie pocztowym iPhone'a, bez względu na to, ile jest wart.
Ryan Olson


4
Dodałbym (ponieważ właśnie popełniłem ten błąd), że jeśli polegasz na silniku szablonów , powinieneś sprawdzić, czy automatycznie dba o ucieczkę encji HTML, czy nie. W moim przypadku Twig robił to, a ja błędnie podwójnie uciekałem przed zapisem &amp;do atrybutu tagu, zamiast używać go bezpośrednio &.
Kamafeather

24

Zgodnie z aktualnymi oficjalnymi zaleceniami HTML, znak ampersand musi zostać zmieniony, np. Jak &amp;w takich kontekstach. Jednak przeglądarki tego nie wymagają, a HTML5 CR proponuje uczynić z tego regułę , więc specjalne reguły mają zastosowanie do wartości atrybutów. Obecne walidatory HTML5 są pod tym względem przestarzałe (zobacz raport o błędzie z komentarzami).

Nadal możliwe będzie uniknięcie znaku ampersand w wartościach atrybutów, ale poza sprawdzaniem poprawności za pomocą aktualnych narzędzi nie ma praktycznej potrzeby ucieczki przed nimi w hrefwartościach (i istnieje niewielkie ryzyko popełnienia błędów, jeśli zaczniesz od nich uciekać).


4
XHTML ( prawdziwy XHTML wysłany jako application/xhtml+xml) najprawdopodobniej zawsze będzie tego wymagał.
zneak

4
Jedno zastrzeżenie do tej zmiany, która jest nadal przedmiotem dyskusji, debaty i niezrozumiany, jest to, że &ma być ok teraz, tak długo, jak to jest „ un niejednoznaczne”. Jednym z oczywistych sposobów uczynienia znaku ampersand niejednoznacznym jest umieszczenie po nim znaków innych niż spacja, a następnie średnika. Że ampersand jest niejednoznaczny i będzie powodować Błąd analizy.
matty

Jak powiedział Jukka, z pewnością istnieje ryzyko zakodowania wszystkich ampersandów, więc zastanów się, jakie jest prawdopodobieństwo, że jeden z twoich href url zawiera średnik. Raczej mało prawdopodobne, ponieważ nie jestem pewien, czy kiedykolwiek widziałem adres URL ze średnikiem. Nie znaczy to, że nie da się tego zrobić. Więc praktycznie mówiąc, nie sądzę, aby było prawdopodobne, że nasze użycie &będzie niejednoznaczne. Dlatego nadal używamy go niezakodowanego w atrybutach href.
matty

Cały powód, dla którego ucieczka jest konieczna, wynika właśnie z możliwości niejasności . Ten konkretny problem może nie polegać na wprowadzeniu wektorów ataku XSS, złego renderowania lub jakiegokolwiek wpływu w 99,99% przypadków, ale nie jest to powód, aby nie przejmować się. Prawidłowe uciekanie jest trudne i zawsze istnieje możliwość popełnienia błędów.
Phil,

5

Publikuję nową odpowiedź, ponieważ uważam, że odpowiedź zneak nie zawiera wystarczającej liczby przykładów, nie pokazuje obsługi HTML i URI jako różnych aspektów i standardów oraz brakuje w niej kilku drobnych rzeczy.

Masz dwa standardy dotyczące adresów URL w linkach ( <a href).

Pierwszym standardem jest RFC 1866 (HTML 2.0), gdzie w „3.2.1. Znaki danych” można odczytać znaki, które muszą zostać zmienione, gdy są używane jako wartość atrybutu HTML. (Same atrybuty w ogóle nie zezwalają na znaki specjalne, np. <a hr&ef="http://...Nie są dozwolone ani nie są <a hr&amp;ef="http://...).

Później przeszło to do standardu HTML 4 , znaki, których potrzebujesz, to:

<   to   &lt;
>   to   &gt;
&   to   &amp;
"   to   &quote;
'   to   &apos;

Drugim standardem jest RFC 3986 „Generic URI standard”, w którym obsługiwane są adresy URL (dzieje się tak, gdy przeglądarka ma zamiar przejść do odsyłacza, ponieważ użytkownik kliknął element HTML).

reserved    = gen-delims / sub-delims

gen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"

sub-delims  = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

Ważne jest, aby uniknąć tych znaków, aby klient wiedział, czy reprezentują dane, czy separator.

Przykład bez zmiany znaczenia:

https://example.com/?user=test&password&te&st&goto=https://google.com

Przykład, w pełni legalny adres URL

https://example.com/?user=test&password&te%26st&goto=https%3A%2F%2Fgoogle.com

Przykład w pełni poprawnego adresu URL w wartości atrybutu HTML:

https://example.com/?user=test&amp;password&amp;te%26st&amp;goto=https%3A%2F%2Fgoogle.com

Również ważne scenariusze:

  • Javascript jako wartość:

    <img src="..." onclick="window.location.href = &quot;https://example.com/?user=test&amp;password&amp;te%26st&amp;goto=https%3A%2F%2Fgoogle.com&quot;;">...</a>(Tak, ;;ma rację).

  • JSON jako wartość:

    <a href="..." data-analytics="{&quot;event&quot;: &quot;click&quot;}">...</a>

  • Elementy uciekające w elementach ze znakami ucieczki, podwójne kodowanie, adres URL wewnątrz adresu URL w parametrze itp., ...

    http://x.com/?passwordUrl=http%3A%2F%2Fy.com%2F%3Fuser%3Dtest&amp;password=&quot;&quot;123


3

Tak, powinieneś przekonwertować &na &amp;.

Ten walidator HTML firmy W3C jest pomocny w przypadku takich pytań. Poinformuje Cię o błędach i ostrzeżeniach dla określonej strony.


1
Nie jestem pewien, czy walidator W3C wykrywa to (bez znaku zmiany znaczenia &w href) jako błąd.
ChrisW

6
Obecnie walidator W3C akceptuje bez zmiany znaczenia i jako ważne. Czy to oznacza, że ​​zmienił się standard i kodowanie nie jest już potrzebne? (czyniąc większość odpowiedzi nieaktualnymi)? Jeśli tak, czy dotyczy to tylko atrybutu href lub dowolnego atrybutu?
matteo
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.