В этом посте я расскажу о моем реальном опыте проверки и о том, какой программный шаблон подходит для логики проверки authn / authz.

Аутентификация и авторизация

Аутентификация и авторизация играют очень важную роль при реализации серверной службы.

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

В чем разница между аутентификацией и авторизацией?

Authn (аутентификация)

Механизм, который проверит, являетесь ли вы собой.

Например, когда вы пытаетесь войти в Medium, вы предоставляете серверу комбинацию имени пользователя и пароля. Имя пользователя / пароль - это очень простой механизм аутентификации для подтверждения вашей личности.

Authz (Авторизация)

Механизм, который проверяет, можете ли вы получить доступ к определенной операции или ресурсам.

Давайте продолжим использовать Medium в качестве примера.

Вы вошли в систему на Medium и пытаетесь удалить мою публикацию на Medium. Если средний сервер разрешает эту операцию, это может быстро стать очень серьезной проблемой безопасности.

К счастью, разработчики в Medium понимают концепцию авторизации, и сервер попытается заблокировать это действие из-за того, что вы не разрешаете выполнять эту операцию.

Хорошо, у нас есть базовое понимание между аутентификацией и авторизацией. Давайте продолжим сегодняшнюю тему шаблон программного обеспечения для логики аутентификации.

Take 1 - Наивная реализация

Теперь мы знаем, насколько важны authn и authz, и пытаемся реализовать соответствующую логику проверки в наших сервисах.

Самый первый подход - написать логику проверки внутри вашего контроллера.

Например, возьмем actix-web view.rs.

Код интегрирует логику проверки аутентификации в существующую службу и довольно прост,

  1. Получить токен из заголовка cookie
  2. Проверьте и подтвердите токен JWT и получите идентификатор и роль пользователя.
  3. Убедитесь, что токен находится в черном списке токенов или нет
  4. Проверьте, является ли роль администратором
  5. В противном случае возвращаем 401 Unauthorized

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

Дубль 2 - Код спагетти и свободное сцепление

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

Код спагетти

Код спагетти - это уничижительное выражение для неструктурированного и сложного в обслуживании исходного кода.
Из Википедии

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

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

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

Краткое изложение приведенного выше примера

(1) бизнес-логика контроллера и логика проверки аутентификации взаимосвязаны

(2) та же логика - копирование и вставка во многие места, поэтому решить проблему с этим логическим блоком непросто

Слабая связь

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

Из википедии

Чтобы сделать логику чище и лучше, можно выделить логику проверки аутентификации в отдельную функцию и поместить ее в нечто вроде модуля app: utils, о котором я упоминал в моем предыдущем посте.

Лучшее решение - применить шаблон декоратора, чтобы украсить исходную функцию контроллера декоратором аутентификации.

Запросить экстрактор

Более удобным решением для actix-web будет использование Request Extractor.

Можно реализовать структуру, реализующую трейт FromRequest, и на основе этого трейта выполнять логику проверки аутентификации.

Плагин actix-web identity - очень хороший пример для демонстрации такого рода паттернов.

Реализация контроллера может использовать что-то вроде следующего фрагмента кода для выполнения логики проверки аутентификации.

Take 3 - Используйте передовой опыт безопасности в дизайне

Подход Request Extractor на самом деле неплох с точки зрения разработчика программного обеспечения, но с точки зрения инженера по безопасности этого может быть недостаточно.

Security Anti Pattern - по умолчанию разрешено

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

Такой подход называется разрешить по умолчанию.

По умолчанию allow предполагает, что к каждой конечной точке может получить доступ кто угодно, если только кто-то явно не запретит это.

В утопии каждый разработчик программного обеспечения имеет смысл написать правильную логику проверки аутентификации; Однако решающая реальность находится на противоположной стороне.

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

Рекомендации по безопасности - отказ по умолчанию

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

Отказ по умолчанию предполагает, что каждая конечная точка требует авторизации, если это не разрешено кем-то явным образом.

Итак, наша цель - найти шаблон, который будет принудительно проверять аутентификацию по умолчанию для каждой конечной точки, чтобы предотвратить возможные ошибки, упомянутые выше.

Шаблон промежуточного программного обеспечения

На мой взгляд, промежуточное ПО отлично подошло бы в такой ситуации.

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

К счастью, actix-web предоставляет очень простой способ интегрировать промежуточное ПО во всю реализацию сервиса.

В следующем фрагменте кода показана идея шаблона промежуточного программного обеспечения. Фрагмент кода выполнит authn_authz_check перед обработкой оставшейся бизнес-логики.

В authn_authz_check нам нужно поддерживать таблицу, явно определяющую, какая конечная точка вообще не требует аутентификации.

Заключительные слова

В этом посте я кратко описал некоторые программные шаблоны для проверки authn / authz, основанные на моем опыте проверки кода безопасности.

Давайте быстро резюмируем некоторые из важнейших тем,

Слабое соединение

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

Запретить по умолчанию лучше, чем разрешить по умолчанию

Люди склонны делать ошибки, и не все инженеры-программисты учитывают при проектировании auth n / authz.
В результате используйте стратегию запрета по умолчанию вместо разрешенной по умолчанию, чтобы еще больше снизить угрозу безопасности в будущем.

Будущая тема

Я рассматриваю только шаблон проектирования программного обеспечения для монолитной внутренней реализации. Я не стал подробно рассказывать о том, как реализовать аутентификацию и авторизацию.

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

Это будут отличные темы для моих будущих публикаций, так что следите за обновлениями.