4 распространенные ошибки разработчиков Node.js

Рост Node.js огромен. Понятно, почему — Node.js помогает нам двигаться быстрее, у него богатая экосистема пакетов, он проверен в боевых условиях, а использование JavaScript позволяет компаниям полностью использовать весь стек и сократить жизненный цикл разработки.

Однако с великими силами приходит и большая ответственность (как я упоминал ранее в своей статье JWT). Подумав о последних 8 годах использования Node.js, я решил опубликовать статью, посвященную четырем распространенным ошибкам разработчиков Node.js.

Большинство из них не специфичны для Node, а скорее являются общими для серверной части. Однако я буду ссылаться на конкретные примеры Node.js, актуальные для любого разработчика в экосистеме.

Ошибка № 1 — Запуск без четко определенных уровней ведения журнала

Я предполагаю, что большинство из нас знакомы с концепцией уровней журнала (DEBUG, INFO, WARN, ERROR и так далее).

Я видел много случаев, когда команда разработчиков торопилась с выпуском нового микросервиса и забывала о четком определении этих уровней журналов.

В этом есть два основных недостатка:

  • Вам и вашим товарищам по команде будет намного сложнее выявлять и устранять проблемы в рабочей среде, если журналы переполнены нерелевантными сообщениями, такими как журналы низкого уровня DEBUG. Обычно они не полезны для производственных рабочих нагрузок.
  • Это значительно увеличит счет за любую службу приема журналов, которую вы используете. Я видел это из первых рук — запуск новой услуги и БУМ — огромный скачок в расходах. Службы приема журналов взимают плату за пропускную способность и/или объем хранилища. 💸

Чтобы решить обе проблемы, убедитесь, что вы используете регистратор с четко определенными уровнями журналирования. Существует множество отличных библиотек логгеров для Node.js (winston, pino, morgan), которые предоставляют вам простой API для создания логов разных типов.

Кроме того, убедитесь, что вы можете настроить уровень журнала вашего приложения во время выполнения с помощью переменной среды (обычно это LOG_LEVEL). Таким образом, вы можете настроить уровень журнала в соответствии со своими потребностями, независимо от того, работаете ли вы локально (устанавливается в файле .env) или при выполнении рабочих нагрузок в облачных средах (Staging, Production и т. д.).

Ошибка № 2 — Бездумный выбор базового образа Dockerfile

Развертывание приложений Node.js в виде контейнеров очень распространено, и это дает много преимуществ. При определении вашего Dockerfile вы объявляете базовый образ для использования в верхней части файла. Например:

FROM node:18

Это означает, что ваш образ будет создан на основе официального образа Node.js версии 18. На что разработчики часто не обращают внимания, так это на потенциальное негативное влияние этого.

Давайте придерживаться примера Node 18. Изображение выше основано на операционной системе Debian. Это полноценная операционная система, которая добавляет много накладных расходов для типичного внутреннего API, написанного на Node.js. Размер образа будет очень большим, его создание займет много времени, хранение будет стоить дороже, а контейнер будет использовать больше ресурсов, что повлияет на вашу масштабируемость и производительность.

Решить это довольно просто — используйте альтернативное изображение. Очень часто можно увидеть альпийскиеи тонкие варианты изображений. В двух словах, это операционные системы на основе Linux, которые очень легкие и не содержат многих двоичных файлов и библиотек, предустановленных в полнофункциональной операционной системе.

Просматривая теги изображений Node.js на Docker Hub, мы видим, что доступны как alpine, так и slim версии. Просто сделав это изменение:

FROM node:18-alpine

Мы сэкономили значительное количество времени на создании образа и минимизировали нагрузку на операционную систему, тем самым оптимизировав общую производительность наших контейнеров. Кроме того, размер полученного образа значительно меньше, что ускоряет его сборку и отправку, а также удешевляет хранение в удаленном реестре контейнеров. Победить! 🥳

Колоссальное уменьшение размера изображения в 5 раз. А теперь представьте, как это повлияет на команду, которая каждый день запускает несколько конвейеров непрерывной интеграции для нескольких сервисов! 🤯

Обратите внимание, что хотя в большинстве случаев это работает, иногда для пакетов вашего приложения требуются определенные низкоуровневые библиотеки, которые по умолчанию не включены в облегченные образы. Вам нужно будет установить их как оператор RUN в вашем Dockerfile. Тем не менее, преимущества того стоят!

Ошибка №3 — Не использовать асимметричное шифрование при подписи веб-токенов JSON (JWT)

Как я писал в своей статье «Веб-токены JSON (JWT) — единственное объяснение, которое вам когда-либо понадобится», веб-токены JSON действительно меняют мир.

Это фантастический инструмент для разработки микросервисов для достижения распределенной авторизации.

Механизм довольно прост — вы подписываете и проверяете токены с помощью криптографии.

Простейшая форма реализации позволяет использовать секрет (например, verySecret123) для подписи токенов. Затем вы будете использовать тот же секрет для проверки этих токенов. Это симметричнаяподпись, поскольку для подписи токена и его проверки используется одно и то же значение.

Если вы делаете это в распределенной архитектуре, каждому из ваших сервисов потребуется доступ к этому секрету для проверки токенов. Это увеличивает вероятность кражи вашего секрета, что может привести к тому, что злоумышленник подпишет поддельные токены, что позволит им повысить доступ или выдавать себя за других и выполнять операции от имени других. Это часто упускается из виду и представляет серьезную угрозу безопасности! 🚨

Лучший способ подписывать JWT — использовать асимметричныйалгоритм. Вместо использования необработанного секретного значения для подписи и проверки токенов вы используете пару ключей (например, сгенерированную с помощью openssl). Результатом является закрытый ключ, используемый для подписи токенов, и открытый ключ, используемый для проверки токенов.

Этот метод значительно более безопасен, поскольку позволяет подписывающему органу (например, вашей службе проверки подлинности) эксклюзивно владеть закрытым ключом и использовать его для подписи токенов.

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

Это значительно снижает риск того, что ваш закрытый ключ будет украден и использован для создания токенов ложных удостоверений и/или повышенных привилегий, путем ограничения количества служб, имеющих к нему доступ.

Если вам интересно и вы хотите узнать больше, я подробно расскажу об этом в моей специальной статье о веб-токенах JSON.

Ошибка №4 — Хранение паролей без уникальной соли

В общем, я категорически против хранения паролей в ваших системах, если только это не является вашим основным бизнесом (что влечет за собой жесткие правила и аудит). Это все веселье и игры, пока что-то не пойдет не так. 👎

Несмотря на это, многие компании предпочитают хранить пароли в своих системах. Это также важная тема, с которой должны быть знакомы бэкенд-разработчики.

➡️ Прежде чем говорить об этой ошибке, краткое введение в аутентификацию по паролю…

Помните, что проверка пароля не является операцией «шифрование-дешифрование». Вы берете необработанный пароль, пропускаете его через алгоритм хеширования и сохраняете, чтобы myPassword123 стало чем-то вроде 487753b945871b5b05f854060de151d8, которое сохраняется в базе данных. Затем, войдя в систему, вы принимаете ввод пользователя и хешируете его. Затем вы сравниваете полученный хэш с хэшем, хранящимся в вашей базе данных, и, если он совпадает, вы аутентифицируете пользователя.

➡️ Теперь мы вместе! Существует четыре уровня безопасности хранения паролей:

  1. Хранение необработанных паролей 😭. Это абсолютное нет-нет. В случае взлома базы данных злоумышленник получит доступ к необработанным паролям всех ваших пользователей.
  2. Хеширование паролей (без соли) 😖. Вы берете пароль пользователя и пропускаете его через алгоритм хеширования, как описано выше, и сохраняете его в своей базе данных. Это предотвратит доступ злоумышленника к необработанным паролям, и это здорово. Однако, поскольку вы просто хешируете пароль, злоумышленник может использовать атаку радужной таблицы, в которой он сравнивает хешированные пароли с их соответствующими необработанными паролями и идентифицирует совпадения. Помните, что запуск myPassword123 через простой алгоритм хеширования всегда будет давать один и тот же результат!
  3. Хеширование паролей + глобальная соль 🥴. Этот метод очень похож на описанный выше, за исключением того, что вы добавляете немного «соли» в пароль перед его хэшированием. Таким образом, вы на самом деле не хэшируете myPassword123, а вместо этого хэшируете myPassword123+SOME_SALT. Это означает, что обычный пароль, такой как myPassword123, будет выглядеть иначе, чем хэш в вашей базе данных, и защитит вас от атак с использованием радужных таблиц. Однако, если ваша глобальная соль раскрыта, злоумышленнику становится легче идентифицировать общие пароли, хранящиеся в вашей базе данных.
  4. Хеширование паролей + уникальная соль для каждого пароля 💪. На сегодняшний день это самый надежный и стандартный метод хранения паролей. Каждый пароль, хранящийся в вашей базе данных, хешируется уникальной солью. Это значительно снижает вероятность того, что злоумышленник получит доступ к необработанным паролям ваших пользователей, даже в случае взлома базы данных. Реализовать это очень просто, используя такой пакет, как Bcrypt.

Опять же, храните пароли ваших пользователей ответственно! Используйте для этого надежный и сертифицированный сервис, если можете, тогда вы сможете сосредоточиться на создании своего основного продукта.

Ребята, это напоминание о том, что вы всегда должны использовать менеджер паролей для автоматической генерации паролей, где бы вы ни регистрировались. Никогда не используйте один и тот же пароль повторно. Вы не знаете, как обрабатываются ваши пароли! ⚠️

Вот и все! Надеюсь, вам понравилась эта статья. Дайте мне знать, что вы думаете в комментариях. Если есть какие-либо другие темы, которые вы считаете интересными, я хотел бы узнать и, возможно, даже написать об этом!

Свяжитесь с нами

Вы можете подписаться на меня здесь, на Medium. Кроме того, не стесняйтесь проверить: