Пользовательское олицетворение пользователя Django
У меня есть приложение Django. Когда вы входите в систему как пользователь admin, я хочу иметь возможность передавать секретный параметр в URL-адрес и вести себя на всем сайте так, как если бы я был другим пользователем.
Скажем, у меня есть URL /my-profile/
, который показывает текущий зарегистрированный профиль пользователя. Я хочу иметь возможность сделать что-то вроде /my-profile/?__user_id=123
и иметь базовое представление, полагая, что я на самом деле являюсь пользователем с ID 123 (таким образом, отображаю этот профиль пользователя).
Зачем мне это нужно?
Просто потому, что намного проще воспроизводить определенные ошибки, которые появляются только в одной учетной записи пользователя.
Мои вопросы:
-
Каким будет самый простой способ реализовать что-то вроде этого?
-
Есть ли какая-либо озабоченность по поводу безопасности, которую я должен иметь в виду при этом? Обратите внимание, что я (очевидно) хочу иметь эту функцию только для пользователей-администраторов, и у наших пользователей-администраторов есть полный доступ к исходному коду, базе данных и т.д., Так что это не действительно "бэкдор"; он просто упрощает доступ к учетной записи пользователя.
Ответы
Ответ 1
Я решил это с помощью простого промежуточного программного обеспечения. Он также обрабатывает перенаправления (то есть параметр GET сохраняется во время перенаправления). Вот он:
class ImpersonateMiddleware(object):
def process_request(self, request):
if request.user.is_superuser and "__impersonate" in request.GET:
request.user = models.User.objects.get(id=int(request.GET["__impersonate"]))
def process_response(self, request, response):
if request.user.is_superuser and "__impersonate" in request.GET:
if isinstance(response, http.HttpResponseRedirect):
location = response["Location"]
if "?" in location:
location += "&"
else:
location += "?"
location += "__impersonate=%s" % request.GET["__impersonate"]
response["Location"] = location
return response
Ответ 2
У меня недостаточно репутации для редактирования или ответа (я думаю), но я обнаружил, что хотя решение ionaut работало в простых случаях, более надежным решением для меня было использование переменной сеанса. Таким образом, даже запросы AJAX подаются правильно, не изменяя URL-адрес запроса, чтобы включить параметр олицетворения GET.
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:
del request.session['impersonate_id']
if request.user.is_superuser and 'impersonate_id' in request.session:
request.user = User.objects.get(id=request.session['impersonate_id'])
Использование:
log in: http://localhost/?__impersonate=[USERID]
log out (back to admin): http://localhost/?__unimpersonate=True
Ответ 3
Похоже, что некоторые другие люди столкнулись с этой проблемой и написали повторно используемые приложения, чтобы сделать это, и по крайней мере некоторые из них перечислены в пакетах django страница для переключения пользователей. Наиболее активными в момент написания являются:
- django-hijack помещает кнопку "hijack" в список пользователей в админе, а также немного вверху страницы, пока вы захватили учетную запись.
- impostor означает, что вы можете войти в систему с именем пользователя "я как другой" и ваш собственный пароль.
- django-impersonate устанавливает URL-адреса, чтобы начать выдавать себя за пользователя, останавливаться, искать и т.д.
Ответ 4
Я не вижу, как это дыра в безопасности, больше, чем использование su - someuser как root на машине unix. root или django-admin с доступом root/admin к базе данных могут подделывать что угодно, если захочет. риск только в учетной записи django-admin, взломанной, и в этот момент взломщик может скрыть дорожки, став другим пользователем, а затем фальсифицирует действия как пользователь.
да, его можно назвать бэкдором, но, как говорит ibz, админы имеют доступ к базе данных в любом случае. возможность внесения изменений в базу данных в этом свете также является бэкдором.
Ответ 5
@Charles Offenbacher отвечает за выдачу себя за пользователей, которые не аутентифицируются с помощью токенов. Однако он не будет работать с клиентскими приложениями, использующими аутентификацию по токенам. Чтобы заставить пользователя работать с приложениями с использованием токенов, нужно напрямую настроить заголовок HTTP_AUTHORIZATION в промежуточном программном обеспечении Impersonate. Мой ответ в основном плагиат Чарльза отвечает и добавляет строки для ручной настройки заголовка.
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:
del request.session['impersonate_id']
if request.user.is_superuser and 'impersonate_id' in request.session:
request.user = User.objects.get(id=request.session['impersonate_id'])
# retrieve user token
token = Token.objects.get(user=request.user)
# manually set authorization header to user token as it will be set to that of the admin (assuming the admin has one, of course)
request.META['HTTP_AUTHORIZATION'] = 'Token {0}'.format(token.key)
Ответ 6
Настройте так, чтобы у вас было два разных имени хоста на одном сервере. Если вы делаете это локально, вы можете подключиться к 127.0.0.1 или localhost, например. Ваш браузер увидит это как три разных сайта, и вы можете войти в систему с разными пользователями. То же самое работает для вашего сайта.
Итак, в дополнение к www.mysite.com вы можете настроить test.mysite.com и войти в систему с пользователем там. Я часто настраивал сайты (с Plone), поэтому у меня есть как www.mysite.com, так и admin.mysite.com, и только разрешаю доступ к этим страницам администратора, что означает, что я могу войти на обычный сайт с именем пользователя, которое имеет проблемы.