Django олицетворение пользователя администратором - PullRequest
20 голосов
/ 11 февраля 2010

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

Допустим, у меня есть URL /my-profile/, который показывает профиль авторизованного пользователя. Я хочу иметь возможность сделать что-то вроде /my-profile/?__user_id=123, и у меня есть базовое представление, что я на самом деле пользователь с идентификатором 123 (таким образом, отображает профиль пользователя).

Почему я этого хочу?

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

Мои вопросы:

  1. Какой самый простой способ реализовать что-то подобное?

  2. Есть ли какие-либо проблемы с безопасностью, которые я должен иметь в виду при этом? Обратите внимание, что я (очевидно) хочу иметь эту функцию только для пользователей-администраторов, и наши пользователи-администраторы в любом случае имеют полный доступ к исходному коду, базе данных и т. Д., Так что это на самом деле не «черный ход»; это просто облегчает доступ к учетной записи пользователя.

Ответы [ 6 ]

33 голосов
/ 12 января 2011

У меня пока недостаточно репутации, чтобы редактировать или отвечать (я думаю), но я обнаружил, что, хотя решение 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
9 голосов
/ 27 февраля 2015

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

  • django-hijack помещает кнопку "hijack" в список пользователей в админке, а также немного вверху страницы, пока вы захватили аккаунт.
  • самозванец означает, что вы можете войти с именем пользователя "me as other" и своим собственным паролем
  • django-impersonate устанавливает URL-адреса для начала олицетворения пользователя, остановки, поиска и т. Д.
9 голосов
/ 11 февраля 2010

Я решил это с помощью простого промежуточного программного обеспечения. Он также обрабатывает перенаправления (то есть параметр 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 голосов
/ 12 февраля 2010

Я не вижу, что это дыра в безопасности больше, чем использование su - someuser в качестве пользователя root на машине с Unix. root или django-admin с доступом root / admin к базе данных могут подделать что угодно, если захотят. риск заключается только в том, что учетная запись django-admin будет взломана, и в этот момент злоумышленник сможет скрыть треки, став другим пользователем, а затем имитировать действия как пользователь.

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

1 голос
/ 20 ноября 2016

@ Ответ Чарльза Оффенбахера отлично подходит для выдачи себя за пользователей, которые не проходят аутентификацию с помощью токенов. Однако он не будет работать с клиентскими приложениями, использующими аутентификацию токена. Чтобы олицетворение пользователя работало с приложениями, использующими токены, необходимо непосредственно установить заголовок 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's token
            token = Token.objects.get(user=request.user)
            # manually set authorization header to user's token as it will be set to that of the admin's (assuming the admin has one, of course)
            request.META['HTTP_AUTHORIZATION'] = 'Token {0}'.format(token.key)
0 голосов
/ 11 февраля 2010

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

Таким образом, в дополнение к www.mysite.com вы можете настроить test.mysite.com и войти туда с пользователем. Я часто настраиваю сайты (с помощью Plone), поэтому у меня есть и www.mysite.com, и admin.mysite.com, и я разрешаю доступ только к страницам администратора оттуда, то есть я могу войти на обычный сайт с именем пользователя, которое имеет проблемы.

...