Tôi có mã hóa ký hiệu trong <a href hè> không?


157

Tôi đang viết mã tự động tạo HTML và tôi muốn nó mã hóa mọi thứ đúng cách.

Giả sử tôi đang tạo một liên kết đến URL sau:

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

Tôi giả định rằng tất cả các giá trị thuộc tính phải được mã hóa HTML. (Vui lòng sửa lại cho tôi nếu tôi sai.) Vì vậy, điều đó có nghĩa là nếu tôi đặt URL ở trên vào thẻ neo, tôi nên mã hóa ký hiệu và như &amp;, như sau:

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

Đúng không?



6
@CiroSantilli: đó là về chuỗi URL thực tế; đây là về cách chúng được mã hóa khi chúng xuất hiện trong các thuộc tính HTML.
JW.

như tôi thấy, mã hóa ampersands không phải lúc nào cũng được yêu cầu trong html5 và câu trả lời đã lỗi thời.
qdinar

Câu trả lời:


175

Vâng, đúng vậy. Các thực thể HTML được phân tích cú pháp bên trong các thuộc tính HTML và việc đi lạc &sẽ tạo ra sự mơ hồ. Đó là lý do tại sao bạn phải luôn luôn viết &amp;thay vì chỉ &bên trong tất cả các thuộc tính HTML.

Điều đó nói rằng, chỉ &và trích dẫn cần phải được mã hóa. Nếu bạn có các ký tự đặc biệt như étrong thuộc tính của mình, bạn không cần mã hóa chúng để đáp ứng trình phân tích cú pháp HTML.

Nó đã từng là trường hợp URL cần được xử lý đặc biệt với các ký tự không phải ASCII, như thế é. Bạn phải mã hóa những cái đó bằng cách sử dụng phần trăm thoát, và trong trường hợp này nó sẽ cung cấp %C3%A9, bởi vì chúng được định nghĩa bởi RFC 1738 . Tuy nhiên, RFC 1738 đã được thay thế bởi RFC 3986 (URI, Mã định danh tài nguyên đồng nhất) và RFC 3987 (IRI, Mã định danh tài nguyên quốc tế), trên đó WhatWG dựa trên công việc của nó để xác định cách các trình duyệt hoạt động khi họ thấy URL không phải ASCII các ký tự trong đó kể từ HTML5 . Do đó, giờ đây an toàn để bao gồm các ký tự không phải ASCII trong URL, được mã hóa theo phần trăm hoặc không.


1
Tôi khá chắc chắn về điều này, nhưng tôi đã có một khoảnh khắc nghi ngờ hiếm hoi. Cảm ơn về lời xác nhận.
JW.

1
Bạn cũng có thể mã hóa khoảng trắng dưới dạng "+" thay vì% 20 - điều này giúp URL dễ đọc hơn.
NickG

1
+ hiện không được tôn trọng trong các liên kết mailto trong ứng dụng thư khách iPhone gốc, với giá trị của nó.
Ryan Olson


4
Tôi sẽ nói thêm (vì tôi vừa rơi vào sai lầm này) rằng nếu bạn đang dựa vào một công cụ mẫu, bạn nên kiểm tra xem điều đó có tự động quan tâm đến việc thoát các thực thể HTML hay không. Trong trường hợp của tôi, Twig đã làm điều đó và tôi đã viết sai hai lần viết &amp;thành thuộc tính thẻ thay vì sử dụng trực tiếp &.
Kamafeather

24

Theo các khuyến nghị HTML chính thức hiện tại, ký hiệu và phải được thoát, ví dụ như &amp;trong các bối cảnh như thế này. Tuy nhiên, các trình duyệt không yêu cầu điều đó và HTML5 CR đề xuất biến quy tắc này thành quy tắc đặc biệt để áp dụng các giá trị thuộc tính. Trình xác thực HTML5 hiện tại đã lỗi thời về mặt này (xem báo cáo lỗi có nhận xét).

Bạn vẫn có thể thoát các ký hiệu trong các giá trị thuộc tính, nhưng ngoài việc xác thực bằng các công cụ hiện tại, không có nhu cầu thực tế để thoát chúng trong hrefcác giá trị (và có một rủi ro nhỏ là phạm sai lầm nếu bạn bắt đầu thoát chúng).


4
Mặc dù vậy, XHTML (XHTML thực sự được gửi dưới dạng application/xhtml+xml) sẽ luôn luôn yêu cầu nó.
zneak

4
Một cảnh báo cho sự thay đổi này, vẫn đang được thảo luận, tranh luận và hiểu lầm, là &bây giờ được cho là ổn, miễn là nó " không mơ hồ". Một cách rõ ràng để làm cho dấu và mơ hồ là theo dõi nó trước với các ký tự không phải không gian và sau đó là dấu chấm phẩy. Ampersand đó hiện không rõ ràng và sẽ gây ra lỗi phân tích cú pháp.
matty

Như Jukka đã nói, chắc chắn có nguy cơ mã hóa tất cả các ký hiệu, vì vậy hãy xem xét khả năng một trong các url của bạn có chứa dấu chấm phẩy như thế nào. Khá khó xảy ra, vì tôi không chắc chắn tôi đã từng thấy một url có dấu chấm phẩy. Không phải là nó không thể được thực hiện. Vì vậy, thực tế mà nói, tôi không nghĩ rằng việc sử dụng chúng ta &sẽ mơ hồ. Do đó, chúng tôi tiếp tục sử dụng thuộc tính in href chưa được mã hóa.
matty

Toàn bộ lý do thoát là cần thiết chính xác là vì khả năng mơ hồ . Vấn đề cụ thể này có thể không giới thiệu các vectơ tấn công XSS, kết xuất xấu hoặc bất kỳ ảnh hưởng nào trong tất cả 99,99% thời gian, nhưng đó không phải là lý do để không bận tâm. Thực hiện thoát hiểm một cách chính xác là khó khăn và luôn có khả năng phạm sai lầm.
Phil

5

Tôi đang đăng một câu trả lời mới vì tôi thấy câu trả lời của zneak không có đủ ví dụ, không hiển thị xử lý HTML và URI như các khía cạnh và tiêu chuẩn khác nhau và còn thiếu một số điều nhỏ.

Bạn có hai tiêu chuẩn liên quan đến URL trong liên kết ( <a href).

Tiêu chuẩn đầu tiên là RFC 1866 (HTML 2.0) trong "3.2.1. Ký tự dữ liệu", bạn có thể đọc các ký tự cần thoát khi được sử dụng làm giá trị cho thuộc tính HTML. (Bản thân các thuộc tính không cho phép các ký tự đặc biệt, ví dụ: <a hr&ef="http://...không được phép, cũng không <a hr&amp;ef="http://....)

Sau này, điều này đã đi vào tiêu chuẩn HTML 4 , các ký tự bạn cần thoát là:

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

Tiêu chuẩn khác là RFC 3986 "Tiêu chuẩn URI chung", trong đó các URL được xử lý (điều này xảy ra khi trình duyệt sắp theo một liên kết vì người dùng đã nhấp vào phần tử HTML).

reserved    = gen-delims / sub-delims

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

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

Điều quan trọng là phải thoát các ký tự đó để khách hàng biết rằng họ đại diện cho dữ liệu hoặc dấu phân cách.

Ví dụ không được giải thoát:

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

Ví dụ, URL hoàn toàn hợp pháp

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

Ví dụ URL hoàn toàn hợp pháp về giá trị của thuộc tính HTML:

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

Các kịch bản quan trọng:

  • Javascript là một giá trị:

    <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>(Vâng, ;;là chính xác.)

  • JSON là một giá trị:

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

  • Những thứ đã thoát bên trong những thứ đã thoát, mã hóa kép, URL bên trong URL bên trong paramter, v.v.

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


3

Có, bạn nên chuyển đổi &sang &amp;.

Công cụ xác thực html này của W3C rất hữu ích cho các câu hỏi như thế này. Nó sẽ cho bạn biết các lỗi và cảnh báo cho một trang cụ thể.


1
Tôi không chắc chắn rằng trình xác nhận W3C phát hiện lỗi này (không được giải thích &trong a href) là một lỗi.
ChrisW

6
Hiện tại, trình xác nhận W3C chấp nhận không thoát và là hợp lệ. Có nghĩa là tiêu chuẩn đã thay đổi và mã hóa không còn cần thiết? (làm cho hầu hết các câu trả lời ở đây đã lỗi thời)? Nếu vậy, điều này chỉ áp dụng cho href hoặc bất kỳ thuộc tính nào?
matteo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.