Комментарии 16
Уже давно использую такую методику на живом проекте на Ruby On Rails, очень удобно. Правда при входе под другим пользователем авторизация админа сбрасывается, но это не доставляет особых неудобств.
Код для Ruby On Rails в связке с Devise
Код для Ruby On Rails в связке с Devise
def become
sign_out :admin
sign_in(:user, User.find(params[:id]))
redirect_to root_url
end
Сбрасываем админа! Так держать! Восхищаюсь — вашему упорству!
У меня более сложный вариант. Пользователь входит всегда под своим паролем. Ведётся в памяти таблица соответствий (RealUser,CurrentUser). Админы могут залогиниться под другим пользователем выставляя значение CurrentUser. Бизнесс-логика завязана на CurrentUser.
В качестве плюшки можно критичные операции блокировать если RealUser != CurrentUser.
В качестве плюшки можно критичные операции блокировать если RealUser != CurrentUser.
Такой вариант имеет право на жизнь, но потребует куда больших изменений. Особенно если сайт уже готовый. Плюс нужны дополнительные телодвижения, что бы заработали полезные встроенные фишки, например атрибуты [PrincipalPermission(…)].
Также намного больше мест где может закрасться ошибка, что тоже важно. Скорее всего, после таких изменений с существующей системе потребуется еще раз проходить аудит безопасности.
Также намного больше мест где может закрасться ошибка, что тоже важно. Скорее всего, после таких изменений с существующей системе потребуется еще раз проходить аудит безопасности.
У меня для таких целей есть просто две сущности пользователей: админы и простые пользователи. Ну и если админ залогинен, то пароль не проверяется.
В такой CMS как Liferay есть такая возможность. Называется «смотреть сайт с позиции другого пользователя».
Картинка made my day
В Zend Framework 1 это одной строчной
Стардартный Auth
и вход под пользователем через админку
Стардартный Auth
$this->_authAdapter = new Zend_Auth_Adapter_DbTable(
$db,
'engine_users',
'user_id',
'password',
"MD5(CONCAT('".$salt."', ?, salt))"
);
и вход под пользователем через админку
$this->_auth->getStorage()->write($user_id);
Когда-то давно делал такое же на django. Без выхода админа, просто подмена текущего юзера через middleware.
class ImpersonateMiddleware(object):
def process_request(self, request):
if request.user.is_superuser and "__impersonate" in request.GET:
request.session['impersonate_id'] = int(request.GET["__impersonate"])
elif "__unimpersonate" in request.GET and 'impersonate_id' in request.session:
del request.session['impersonate_id']
if request.user.is_superuser and 'impersonate_id' in request.session:
request.can_unimpersonate = True
request.user = User.objects.get(id=request.session['impersonate_id'])
В Symfony2 есть такая возможность (+ вернуться обратно в админы) из коробки.
New emergency number www.youtube.com/watch?v=HWc3WY3fuZU
Мы имеем аналогичный функционал в nopCommerce (open-source shopping cart), который используется персоналом магазинов для размещения заказов от имени покупателей, оформляющих покупки по телефону
В мире Windows Authentication есть уже готовое красивое решение под названием Impersonation. Т.е. когда один пользователь как-бы прикидывается другим, получая его права и возможность выполнять действия от его имени.
А как я смогу подпихнуть креденшлы другого пользователя, зная только имя? Ведь куку не подменить — не используются (или я не видел чтобы использовались куки+win auth).
Все правильно, залогиниться под любым пользователем винды просто так не получиться не имея токена или пароля. Разве что LOCAL/NETWORK SERVICE если достаточно прав.
Абстрактный пример:
Но можно например спросить креды раз и сохранить токен что бы можно было в дальнейшем выполнять действия от этого пользователя, т.е. как-бы получить у него согласие на такую операцию. Хранить кстати пароль постоянно в такой ситуации нет необходимости. Как пример виндовый шедулер, один раз задаче разрешаем выполняться от любого пользователя и все.
Но тут очень все зависит от конкретной ситуации, если это, например, корп. сайт в интранете, который предоставляет доступ к какой-то информации из своей базы то подмену нужно делать уже после входа и перед получением данных.
Предположим что сайт решает какую именно инфу выгребать, вызывая что то типа WindowsIdentity.GetCurrent().Name. Тогда можно завернуть этот вызов во что-то, что будет возвращать другого пользователя.
Вообще с win auth решение сильно зависит от того к чему нужно получить доступ.
Абстрактный пример:
LogonUser("LOCAL SERVICE", String.Empty, String.Empty, 5 /* service-type logon */, 0, out userToken);
DuplicateToken(userToken, 2, ref userToken2);
identity = new WindowsIdentity(userToken2);
context = identity.Impersonate();
...
context.Undo();
Но можно например спросить креды раз и сохранить токен что бы можно было в дальнейшем выполнять действия от этого пользователя, т.е. как-бы получить у него согласие на такую операцию. Хранить кстати пароль постоянно в такой ситуации нет необходимости. Как пример виндовый шедулер, один раз задаче разрешаем выполняться от любого пользователя и все.
Но тут очень все зависит от конкретной ситуации, если это, например, корп. сайт в интранете, который предоставляет доступ к какой-то информации из своей базы то подмену нужно делать уже после входа и перед получением данных.
Предположим что сайт решает какую именно инфу выгребать, вызывая что то типа WindowsIdentity.GetCurrent().Name. Тогда можно завернуть этот вызов во что-то, что будет возвращать другого пользователя.
Вообще с win auth решение сильно зависит от того к чему нужно получить доступ.
Есть пока только подозрение о невозможности подмены пользователя при authentication=windows.
Когда-то я пробовал запускать отдельный поток от имперсонированного пользователя (да даже просто с win-аутентификацией и impersonate=false).
Если память не изменяет, то креденшлы пользователя подчищаются как только обработка запроса пользователя закончена.
Имею ввиду, что до домента return View() в отдельно работающем потоке всё хорошо. Но сразу отсоединения пользователя — созданный поток продолжает работать, а HttpContext.Current уже обнулен и инстансы IPrincipal и IIdentity задиспозены. Прятать инстансы креденшлов я не сумел — диспозятся отовсюду.
Пока делаю вывод что на чистой 401-негоциации не получится.
Но на выходные Вы нашли мне развлечение, вот спасибо.
Когда-то я пробовал запускать отдельный поток от имперсонированного пользователя (да даже просто с win-аутентификацией и impersonate=false).
Если память не изменяет, то креденшлы пользователя подчищаются как только обработка запроса пользователя закончена.
Имею ввиду, что до домента return View() в отдельно работающем потоке всё хорошо. Но сразу отсоединения пользователя — созданный поток продолжает работать, а HttpContext.Current уже обнулен и инстансы IPrincipal и IIdentity задиспозены. Прятать инстансы креденшлов я не сумел — диспозятся отовсюду.
Пока делаю вывод что на чистой 401-негоциации не получится.
Но на выходные Вы нашли мне развлечение, вот спасибо.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Логинимся на сайт под чужим аккаунтом не имея пароля