Недавно я работал над задачей кодирования для одной компании и наткнулся на нечто, что сначала показалось очень странным. Задача состояла в том, чтобы воспроизвести инструмент сравнения внешнего интерфейса из макета png и файла JSON, имитирующего вызов API.

Поэкспериментировав с моими возможностями flexbox, я наткнулся на раздел пользовательского интерфейса, с которым я не был знаком. Это был неупорядоченный список функций для различных планов, показанных в инструменте. Просмотрев файл JSON, я нашел информацию, необходимую для создания этого списка. Значением объекта была строка, содержащая HTML-элементы ‹ul› и ‹li›.

Сначала я подумал о том, чтобы просто поместить эту строку между div, но понял, что это просто вернет HMTL в виде текста. Хотя я не мог понять, каким будет решение React, эта проблема напомнила мне о нацеливании и вставке текста в элементы HTML с помощью innerHTML. Из этого я смог найти эквивалент React, опасно SetInnerHTML.

Прежде чем мы углубимся в этот атрибут, я хочу уделить немного времени обзору того, как свойства и атрибуты используются в React. React использует виртуальный DOM для повышения производительности и совместимости с браузерами и даже имеет измененные свойства и атрибуты. React использует camelCase для имен свойств и атрибутов и даже изменил имена некоторых атрибутов и способ их использования.

Если вы работали с React раньше, вы заметили, что обработчики событий отображаются как «onClick» вместо «click», но React делает шаг вперед с другими, такими как изменение innerHTML на опасноSetInnerHTML. Всегда обращайтесь к документации, если у вас есть вопросы (ссылка в ресурсах).

Вы можете использовать свойство объекта JavaScript innerHMTL для ряда целей. Хотя вы можете вставлять строки из вызова API в элементы отображения, это также полезно для оповещения пользователей об ошибках в форме. Ниже я собрал короткую демонстрацию, в которой я создаю простую единую форму ввода, которая будет принимать ввод пользователя и отображать ошибку, если пользователь не вводит имя:

Здесь у нас настроена форма, включая пустой div с классом сообщения об ошибке между меткой и вводом. Несмотря на то, что существуют способы обращения с сообщениями об ошибках, в которых вы переключаете имена классов, чтобы сообщение об ошибке отображалось, например, «отображать: нет» на «отображать: блокировать», здесь мы собираемся просто вставить текст в элемент p сообщения об ошибке, если проверка формы не удалась. В данном случае это не так, поэтому мы устанавливаем для свойства innerHTML нашего объекта ошибки текст сообщения об ошибке, который затем отображается на нашем экране. Теперь наш пользователь знает, что ему нужно исправить информацию, прежде чем двигаться дальше, отлично!

React работает по-другому в своем подходе к настройке HTML из кода. Одной из проблем при настройке HTML из кода является риск XSS или межсайтового скриптинга. Это атака типа вредоносной инъекции, которая часто используется в ситуациях, когда пользователь вводит информацию, которая затем отображается в виде вывода в приложении. Из-за этого React назвал свою версию innerHTML опасноSetInnerHTML. Это название является напоминанием разработчикам о том, что этот метод кодирования может подвергнуть пользователей риску.

Несмотря на то, что это сопряжено с риском, это не опасно, если вы принимаете надлежащие меры предосторожности, такие как использование библиотеки для санации пользовательских входных данных до того, как ваш код использует эти входные данные, и использование правил eslint для предупреждения о проблемах с грязным кодом во время разработки. В ресурсах есть ссылка на то, как правильно дезинфицировать код, чтобы сделать опасно SetInnerHTML безопасным для использования.

Наряду со сменой имени React использует другой механизм установки значения элемента. Вместо того, чтобы просто установить значение элемента в виде строки, как мы сделали в приведенном выше примере с ванильным JavaScript, вы должны передать атрибуту объект. React требует использования этого атрибута в формате опасноSetInnerHTML = {__html : «ваш код» }. В этом нет ничего особенного, кроме того, что дополнительные усилия напоминают вам, что этот код может быть опасным.

Я собрал краткий пример того, как использовать опасно SetInnerHTML, основываясь на ситуации, с которой я столкнулся во время выполнения домашнего задания. Ниже у меня есть изображение json-файла mock API:

Вы можете видеть, что у нас есть несколько полей для каждого рецепта, включая название блюда, количество человек, которое оно обслуживает, время приготовления и строку HTML со списком ингредиентов. Наш компонент React будет очень простым и сосредоточится только на названии и ингредиентах:

Здесь мы получаем свойства заголовка и ингредиентов в наш компонент и хотим отобразить их в нашей карточке. Заголовок просто передается как JSX для элемента div, но мы должны использовать что-то другое для строки HTML, содержащей наши ингредиенты. Здесь мы обращаемся кhazardlySetInnerHTML, чтобы вставить наш текст в div. Используя атрибутопасноSetInnerHTML, мы передаем ему объект с ключом __html, а наши ингредиенты поддерживаются в качестве значения для вставки и возвращаются нашей карточке!

Хотя есть и другие способы сообщения об ошибках или показа текста внутри элемента div, атрибутhazardlySetInnerHTML очень удобен, когда вам нужен быстрый способ вставки строки HTML в элемент. Хотя он представляет возможности XSS, их можно уменьшить или удалить, правильно очистив пользовательский ввод. Надеюсь, вам понравилась эта статья. Оставьте комментарий, если вы использовали или планируете использовать опасно SetInnerHTML в своих проектах!

Ресурсы

https://reactjs.org/docs/dom-elements.html

https://owasp.org/www-community/attacks/xss/

https://dev.to/jam3/how-to-prevent-xss-attacks-when-using-dangeroussetinnerhtml-in-react-1464