mix phx.gen.auth
Исходный кодКоманда mix phx.gen.auth генерирует гибкую готовую систему аутентификации для вашего приложения Phoenix. Этот генератор позволяет быстро перейти от задачи добавления аутентификации в кодовую базу к решению реальной проблемы, ради которой создаётся приложение. Поддерживаются следующие возможности:
- Регистрация пользователей с подтверждением учётной записи по электронной почте
- Вход по магическим ссылкам
- Аутентификация по паролю по выбору пользователя
- «Режим sudo», также известный как привилегированная аутентификация, при котором пользователь должен подтвердить свою личность перед выполнением конфиденциальных действий
Начало работы
Перед запуском этой команды рекомендуется сохранить текущие изменения в коммите, поскольку она создаёт несколько файлов.
Для начала выполним следующую команду из корневого каталога приложения:
$ mix phx.gen.auth Accounts User users An authentication system can be created in two different ways: - Using Phoenix.LiveView (default) - Using Phoenix.Controller only Do you want to create a LiveView based authentication system? [Y/n] Y
Первый аргумент — модуль контекста, за которым следуют модуль схемы и её имя во множественном числе (используемое как имя таблицы схемы). Пример выше создаст модуль контекста Accounts с двумя схемами: User и UserToken. Модуль контекста помогает сгруппировать все схемы, связанные с аутентификацией. Вы можете выбрать имена контекста и схем по своему усмотрению.
Генераторы аутентификации поддерживают Phoenix LiveView для улучшения взаимодействия с пользователем, поэтому здесь следует ответить Y. Также можно ответить n, чтобы использовать систему аутентификации на основе контроллеров. Оба подхода создают одинаковые контекст и схемы, используя одни и те же имена таблиц и пути маршрутов.
Поскольку этот генератор установил дополнительные зависимости в mix.exs, загрузим их:
$ mix deps.get
Теперь выполним ожидающие миграции репозитория:
$ mix ecto.migrate
Запустим тесты, чтобы убедиться, что новая система аутентификации работает как ожидалось.
$ mix test
И наконец, запустим сервер Phoenix и проверим результат (обратите внимание на новые ссылки Register и Log in в правом верхнем углу страницы по умолчанию).
$ mix phx.server
Обязанности разработчика
Поскольку Phoenix генерирует этот код в вашем приложении, а не включает эти модули непосредственно в Phoenix, вы получаете полную свободу изменять систему аутентификации в соответствии с вашими задачами. Единственный нюанс использования сгенерированной системы аутентификации заключается в том, что после генерации она не будет обновляться. Поэтому, когда в результат работы mix phx.gen.auth вносятся улучшения, вам предстоит решить, нужно ли переносить эти изменения в ваше приложение. Улучшения, связанные с безопасностью, и другие важные изменения будут явно отмечены в файле CHANGELOG.md и примечаниях к обновлению.
Сгенерированный код
Ниже приведены примечания о сгенерированной системе аутентификации.
Запрет доступа
В сгенерированный код входит модуль аутентификации с несколькими плагами, которые извлекают текущего пользователя, требуют аутентификации и выполняют другие задачи. Например, в приложении с именем MyApp, для которого был запущен mix phx.gen.auth Accounts User users, вы найдёте модуль MyAppWeb.UserAuth с такими плагами, как:
-
fetch_current_scope_for_user— извлекает данные текущего пользователя, если они доступны, и сохраняет их в назначении:current_scope -
require_authenticated_user— должен вызываться послеfetch_current_scope_for_userи требует, чтобы текущий пользователь существовал и прошёл аутентификацию -
redirect_if_user_is_authenticated— используется для нескольких страниц, которые не должны быть доступны аутентифицированным пользователям (создаётся только для аутентификации на основе контроллеров) -
require_sudo_mode— используется для страниц с конфиденциальными операциями и требует недавней аутентификации
Области видимости
Сгенерированный код включает модуль области видимости. В приложении с именем MyApp, для которого был запущен mix phx.gen.auth Accounts User users, вы найдёте следующий модуль в lib/my_app/accounts/scope.ex:
defmodule MyApp.Accounts.Scope do
# ...
alias MyApp.Accounts.User
defstruct user: nil
@doc """
Creates a scope for the given user.
Returns nil if no user is given.
"""
def for_user(%User{} = user) do
%__MODULE__{user: user}
end
def for_user(nil), do: nil
end
Структура данных области видимости хранится в assigns и доступна контроллерам и LiveView. По мере усложнения приложения эта структура данных может хранить важные метаданные, например сведения о командах, компаниях или организациях, к которым принадлежит пользователь, разрешениях, телеметрических данных, таких как IP-адрес, и так далее.
Кроме того, при будущих запусках генераторов Phoenix эта структура данных будет автоматически передаваться из контроллеров и LiveView в большинство операций контекста, чтобы гарантировать, что новые данные будут ограничены текущим пользователем, командой, компанией или организацией. Области видимости необходимы для того, чтобы пользователь мог получать доступ только к принадлежащим ему данным. Подробнее об этом рассказано в руководстве «Области видимости».
Хеширование паролей
По умолчанию для хеширования паролей в Unix-системах используется bcrypt, а в Windows-системах — pbkdf2. Обе системы используют интерфейс Comeonin.
Механизм хеширования паролей можно переопределить с помощью параметра --hashing-lib. Поддерживаются следующие значения:
-
bcrypt— bcrypt_elixir -
pbkdf2— pbkdf2_elixir -
argon2— argon2_elixir
Рекомендуем разработчикам рассмотреть возможность использования argon2 — наиболее надёжного из всех трёх вариантов. Недостаток заключается в том, что argon2 требует значительных ресурсов процессора и памяти, поэтому для запуска приложений понадобятся более мощные экземпляры.
Подробнее о выборе этих библиотек см. в проекте Comeonin.
Для аутентификации на основе LiveView предусмотрены аналогичные хуки :on_mount.
Уведомления
Сгенерированный код не интегрирован с системой отправки SMS или электронных писем для подтверждения учётных записей, сброса паролей и т. д. Вместо этого он просто записывает сообщение в терминал. После генерации вам необходимо самостоятельно интегрировать подходящую систему.
Обратите внимание: если вы создали проект Phoenix с помощью mix phx.new, по умолчанию он настроен на использование почтового модуля Swoosh. Чтобы просматривать письма уведомлений во время разработки с помощью Swoosh, перейдите по адресу /dev/mailbox.
Параллельные тесты
Сгенерированные тесты выполняются параллельно, если вы используете базу данных, поддерживающую параллельные тесты, например PostgreSQL.
Подробнее о mix phx.gen.auth
Дополнительные сведения см. в mix phx.gen.auth, в том числе об использовании другой библиотеки хеширования паролей, настройке пространства имён веб-модуля, генерации двоичного типа идентификатора, настройке параметров по умолчанию и использовании пользовательских имён таблиц.
Вопросы безопасности
Отслеживание сеансов
Все сеансы и токены отслеживаются в отдельной таблице. Это позволяет определить количество активных сеансов для каждой учётной записи. При желании эту информацию можно показывать пользователям.
Обратите внимание: при изменении пароля (в результате сброса или напрямую) все токены удаляются, и пользователю приходится заново входить в систему на всех устройствах.
Атаки с перечислением пользователей
Атака с перечислением пользователей позволяет выяснить, зарегистрирован ли адрес электронной почты в приложении. Сгенерированный код аутентификации не пытается защитить от таких атак. Например, при регистрации учётной записи, если адрес уже зарегистрирован, код сообщит пользователю об этом.
Если ваше приложение уязвимо для атак с перечислением, необходимо реализовать собственные сценарии, которые, как правило, сильно отличаются от сценариев большинства приложений: нужно тщательно соблюдать баланс между безопасностью и удобством для пользователей.
Кроме того, если вас беспокоят атаки с перечислением, следует учитывать и атаки по времени выполнения. Например, регистрация новой учётной записи обычно требует дополнительных действий (например, записи в базу данных, отправки электронных писем и т. д.) по сравнению со случаем, когда учётная запись уже существует. Злоумышленник может измерить время выполнения этих дополнительных действий и таким образом выявить зарегистрированные адреса. Это относится ко всем конечным точкам (регистрации, входу и т. д.), которые могут отправлять электронные письма, уведомления в приложении и прочее.
Атаки на подтверждение учётных записей и предварительный подбор учётных данных
В сгенерированный функционал входит механизм подтверждения учётной записи, обычно по электронной почте. Кроме того, для предотвращения проблем с безопасностью сгенерированный код запрещает пользователям работать с приложением, пока их учётные записи не подтверждены. Чтобы изменить это поведение, обратитесь к разделу «Сочетание регистрации по магической ссылке и паролю» в документации mix phx.gen.auth.
Чувствительность к регистру
Поиск адресов электронной почты выполняется без учёта регистра. В MySQL и MSSQL поиск без учёта регистра используется по умолчанию. В SQLite3 для его поддержки в определении столбца используется COLLATE NOCASE. В PostgreSQL используется расширение citext.
Обратите внимание: citext является частью самого PostgreSQL и входит в его состав в большинстве операционных систем и менеджеров пакетов. mix phx.gen.auth создаёт расширение, поэтому в большинстве случаев никаких дополнительных действий не требуется. Если по какой-либо причине менеджер пакетов распространяет citext в виде отдельного пакета, при выполнении миграции возникнет ошибка. Скорее всего, её можно устранить, установив пакет postgres-contrib.
Дополнительные ресурсы
Переход на магические ссылки и режим sudo в Phoenix v1.8
В Phoenix v1.8 появились новые возможности, а код аутентификации стал проще. Разработчикам не обязательно переходить на новые генераторы, хотя мы рекомендуем настроить собственную область видимости, как описано в руководстве «Области видимости».
Если вы сгенерировали код аутентификации с помощью mix phx.gen.auth в Phoenix v1.7 или более ранней версии и хотите перейти на новые генераторы, воспользуйтесь следующими запросами на включение изменений в качестве примеров:
- Запрос на включение изменений для перехода с Phoenix 1.7 на основе LiveView
phx.gen.authна магические ссылки - Запрос на включение изменений для перехода с Phoenix 1.7 на основе контроллеров
phx.gen.authна магические ссылки
Помните, что новая система аутентификации полностью исключает регистрацию учётной записи с паролем, упрощая и пользовательский интерфейс, и сгенерированный код. Поэтому при переходе не изменяйте существующие файлы миграций: вместо этого сделайте столбец hashed_password необязательным, установив null: true. Кроме того, при переходе на новую систему и удалении таких возможностей, как «Забыли пароль?», после разрешения значений NULL для столбца необходимо установить hashed_password всех неподтверждённых учётных записей в nil, чтобы избежать атак с подбором учётных данных. Поэтому мы рекомендуем развёртывать обновлённую систему аутентификации в периоды низкой нагрузки, когда желательно, чтобы пароль не был сброшен в NULL у пользователя, только что зарегистрировавшего учётную запись. Если такой компромисс неприемлем, можно добавить магические ссылки поверх существующей системы аутентификации без полного перехода — подробнее об этом рассказано здесь.
Первоначальная реализация
По следующим ссылкам можно ознакомиться с первоначальной реализацией системы аутентификации, использовавшейся по умолчанию до Phoenix v1.7:
- Публикация в блоге José Valim — Новая система аутентификации для Phoenix
- Публикация в блоге Berenice Medel о создании LiveView для аутентификации (вместо традиционных контроллеров и представлений) — Аутентификация Phoenix в действии
- Исходная спецификация проекта
- Запрос на включение изменений для базового приложения Phoenix
© 2014 Chris McCord
Licensed under the MIT License.
https://phoenix.hexdocs.pm/mix_phx_gen_auth.html