Codifico e comercial em <a href…>?

157

Estou escrevendo um código que gera automaticamente HTML e quero que ele codifique as coisas corretamente.

Digamos que estou gerando um link para o seguinte URL:

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

Estou assumindo que todos os valores de atributo devem ser codificados em HTML. (Corrija-me se estiver errado.) Isso significa que, se eu estiver colocando o URL acima em uma tag de âncora, codificarei oe comercial da &amp;seguinte forma:

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

Isso está correto?

JW.
fonte
possível duplicação de Quais caracteres tornam um URL inválido?
Ciro Santilli publicou 29/08/14
6
@CiroSantilli: trata-se de strings de URL reais; trata-se de como eles são codificados quando aparecem em atributos HTML.
JW.
como eu vejo, nem sempre é necessário codificar e comercial no html5, e as respostas estão desatualizadas.
qdinar
1
pergunta para html5: stackoverflow.com/questions/19441750/…
qdinar

Respostas:

175

Sim, ele é. As entidades HTML são analisadas dentro dos atributos HTML e uma dispersão &criaria uma ambiguidade. É por isso que você sempre deve escrever em &amp;vez de apenas &dentro de todos os atributos HTML.

Dito isto, apenas &e aspas precisam ser codificadas. Se você tiver caracteres especiais, como éno seu atributo, não precisará codificá-los para satisfazer o analisador HTML.

Costumava ser o caso de URLs precisarem de tratamento especial com caracteres não ASCII, como é. Você precisava codificar aqueles que usavam escapes percentuais e, nesse caso, daria %C3%A9, porque eles foram definidos pela RFC 1738 . No entanto, o RFC 1738 foi substituído pelo RFC 3986 (URIs, Uniform Resource Identifiers) e RFC 3987 (IRIs, Internationalized Resource Identifiers), no qual o WhatWG baseou seu trabalho para definir como os navegadores devem se comportar quando virem um URL com ASCII não. caracteres desde HTML5 . Portanto, agora é seguro incluir caracteres não ASCII em URLs, codificados em porcentagem ou não.

zneak
fonte
1
Eu tinha certeza disso, mas tive um raro momento de dúvida. Obrigado por confirmar.
JW.
1
Você também pode codificar espaços como "+" em vez de% 20 - o que facilita a leitura do URL.
precisa saber é
1
Atualmente, o + não é respeitado nos links mailto no cliente de email nativo do iPhone, pelo que vale a pena.
Ryan Olson
1
éainda precisa de codificação: stackoverflow.com/questions/2742852/unicode-characters-in-urls
lulalala
4
Eu acrescentaria (como acabei de cometer esse erro) que, se você estiver contando com um mecanismo de modelo, deverá verificar se isso cuida automaticamente da fuga de entidades HTML ou não. No meu caso, Twig estava fazendo isso, e eu estava erradamente escapando a escrever &amp;no atributo tag em vez de usá-lo diretamente &.
Kamafeather
24

Pelas recomendações oficiais atuais do HTML, o e comercial deve ser escapado, por exemplo, como &amp;em contextos como este. No entanto, os navegadores não precisam, e o HTML5 CR propõe fazer disso uma regra , para que regras especiais sejam aplicadas nos valores dos atributos. Os validadores HTML5 atuais estão desatualizados a esse respeito (consulte o relatório de erros com comentários).

Continua sendo possível escapar dos e comerciais nos valores dos atributos, mas, além da validação com as ferramentas atuais, não há necessidade prática de evitá-los nos hrefvalores (e há um pequeno risco de cometer erros se você começar a evitá-los).

Jukka K. Korpela
fonte
4
XHTML (XHTML real enviado como application/xhtml+xml) provavelmente sempre o exigirá.
Zneak
4
Uma ressalva a essa mudança, que ainda está sendo discutida, debatida e incompreendida, é que ela &deveria estar bem agora, desde que seja " un ambígua". Uma maneira óbvia de tornar o e comercial ambíguo é segui-lo primeiro com caracteres não espaciais e, em seguida, um ponto e vírgula. Isso comercial agora é ambígua, e irá causar um erro de análise.
matty
Como Jukka disse, certamente há um risco de codificar todos os e comerciais, portanto, considere a probabilidade de um de seus URLs href conter um ponto e vírgula. Bastante improvável, pois não tenho certeza se já vi um URL com ponto e vírgula. Não que isso não possa ser feito. Então, na prática, não acho provável que nosso uso &seja ambíguo. Portanto, continuamos a usá-lo não codificado em atributos href.
matty
Todo o motivo pelo qual a fuga é necessária é justamente devido à possibilidade de uma ambiguidade . Esse problema específico pode não estar introduzindo vetores de ataque XSS, renderização incorreta ou qualquer efeito em 99,99% do tempo, mas esse não é um motivo para não se preocupar. Escapar corretamente é difícil e sempre há a possibilidade de cometer erros.
Phil
5

Estou postando uma nova resposta porque acho que a resposta do zneak não tem exemplos suficientes, não mostra o manuseio de HTML e URI como aspectos e padrões diferentes e tem algumas pequenas coisas ausentes.

Você tem dois padrões sobre URLs nos links ( <a href).

O primeiro padrão é o RFC 1866 (HTML 2.0), onde em "3.2.1. Caracteres de Dados" você pode ler os caracteres que precisam ser escapados quando usados ​​como valor para um atributo HTML. (Os atributos em si não permitem caracteres especiais, por exemplo, <a hr&ef="http://...não é permitido nem é <a hr&amp;ef="http://....)

Posteriormente, isso passou para o padrão HTML 4 , os caracteres dos quais você precisa escapar são:

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

O outro padrão é o RFC 3986 "Padrão de URI genérico", em que os URLs são manipulados (isso acontece quando o navegador está prestes a seguir um link porque o usuário clicou no elemento HTML).

reserved    = gen-delims / sub-delims

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

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

É importante escapar desses caracteres para que o cliente saiba se eles representam dados ou um delimitador.

Exemplo sem escape:

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

Exemplo, URL totalmente legítimo

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

Exemplo de URL totalmente legítimo no valor do atributo HTML:

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

Também cenários importantes:

  • Javascript como um valor:

    <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>(Sim, ;;está correto.)

  • JSON como um valor:

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

  • Escapou coisas dentro de coisas escapadas, codificação dupla, URL dentro de URL dentro de parâmetro etc, ...

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

Daniel W.
fonte
3

Sim, você deve converter &para &amp;.

Essa ferramenta de validação html do W3C é útil para perguntas como esta. Ele informará os erros e avisos de uma página específica.

Randy Greencorn
fonte
1
Não tenho certeza de que o validador W3C detecte isso (sem escape &em um href) como um erro.
ChrisW
6
Atualmente, o validador W3C aceita sem escape e como válido. Isso significa que o padrão mudou e a codificação não é mais necessária? (tornando a maioria das respostas aqui desatualizadas)? Em caso afirmativo, isso se aplica apenas ao href ou a qualquer atributo?
Matteo