Вход из кода - авторизация без пароля и работа под другим пользователем
Разбираем вход без пароля: чем он отличается от обычной авторизации, как зайти под покупателем для разбора его заказа и как из этого выйти.
Решение
Авторизуем пользователя по идентификатору:
global $USER;$USER->Authorize($userId); // вход без проверки пароляprintf("вошли как %s (%d)\n", $USER->GetLogin(), $USER->GetID());// проверку прав делает вызывающий код: сам вызов ничего не проверяетВход по идентификатору не проверяет ни пароль, ни право на такой вход. Это рабочий инструмент для своих сценариев и одновременно готовая дыра, если вызов попадёт в код, доступный посетителю.
Заходим под другим пользователем из-под администратора:
if (!$USER->IsAdmin()) { return; } // проверка обязательна$_SESSION['ADMIN_BACK_ID'] = $USER->GetID(); // запоминаем, кем были$USER->Authorize($customerId);LocalRedirect('/personal/'); // переход обязателен: страница уже собранаСвой прежний идентификатор сохраняют до самой подмены. Без этого возврат делается только повторным входом с паролем, а на боевом сайте это означает разлогинить себя в разгар разбора.
Возвращаемся обратно:
$backId = (int)($_SESSION['ADMIN_BACK_ID'] ?? 0);if ($backId) { unset($_SESSION['ADMIN_BACK_ID']); $USER->Authorize($backId); // возврат - такая же авторизация LocalRedirect('/bitrix/admin/'); // и снова переход после смены}Возврат устроен ровно так же, как и сама подмена. Забытая запись в сеансе оставляет администратора в чужой учётной записи после закрытия вкладки, и следующий заход он делает уже покупателем.
Завершаем сеанс полностью:
$USER->Logout();$conn = \Bitrix\Main\Application::getConnection();$conn->query('DELETE FROM b_user_stored_auth WHERE USER_ID = ' . (int)$USER->GetID());// запомненный вход живёт отдельно и переживает обычный выход// после удаления записи браузер больше не заходит сам// внешний вход через сервис доходит до этого же места авторизацииОбычный выход завершает текущий сеанс, но не трогает запомненный вход. Пока запись цела, браузер заходит снова сам, и жалоба «выход не работает» означает именно это.
Вход из кода стоит закрывать отдельным правом, а не проверкой на администратора. Разбором заказов занимается служба поддержки, и выдавать ей полные права ради одной кнопки - плохой размен.
Вход по почтовому адресу включается отдельной настройкой и требует уникальности этого адреса. Две учётные записи с одной почтой делают вход неоднозначным, и платформа в этом случае пускает того, кого нашла первым.
Действия под чужой учётной записью стоит записывать в отдельный журнал. Заказ, изменённый «покупателем» в три часа ночи, объясняется куда быстрее, если рядом лежит запись о том, кто из сотрудников тогда зашёл под ним.
Типичные проблемы
Посетитель может войти под чужой записью.
Вход по идентификатору вызывается без всякой предварительной проверки прав. Сам вызов никаких проверок не делает и пускает под кого угодно из базы.
Администратор остался покупателем.
Свой идентификатор не был сохранён в сеансе перед подменой. Вернуться обратно после этого можно только обычным входом с паролем.
После выхода вход происходит сам.
Запомненный вход хранится отдельной записью в таблице базы. Обычный выход эту отдельную запись не трогает и не удаляет.
Права после входа из кода не те.
Страница была собрана ещё до смены текущего пользователя. После подмены пользователя делают переход на другой адрес, чтобы страница собралась заново.
Вход по почте пускает не того.
Один почтовый адрес указан сразу у двух учётных записей. Вход по почте требует её полной уникальности среди всех пользователей сайта.
Частые вопросы
Чем вход по идентификатору отличается от обычного?
Он не проверяет пароль и не вызывает событий проверки. Поэтому его держат подальше от кода, доступного посетителям.
Как выйти из-под покупателя без пароля?
Повторной авторизацией по сохранённому идентификатору администратора. Сохранять его нужно до подмены.
Видно ли в журнале, кто заходил под покупателем?
Штатно нет: платформа видит обычный вход. Такую запись добавляют своим кодом при подмене.
Можно ли пускать по одноразовой ссылке?
Да, проверив свою метку и время её жизни, а потом авторизовав из кода. Ссылка без срока жизни превращается в вечный пропуск.
Смежное
- Авторизация и сессии - оглавление подтемы
- Страница и форма авторизации: компоненты, шаблоны, возврат после входа - обычный вход с паролем
- Слетает авторизация: время жизни сессии и запоминание входа - откуда берётся запомненный вход
- Забыт пароль и потерян доступ в админку - когда входить нечем
- Пользователи, группы и права - устройство прав целиком
- Защита входа: перебор паролей, картинка с кодом, второй фактор - защита формы входа от перебора
- Вход через внешний сервис: регистрация приложения, привязка, первый вход - вход чужими руками