Django отправляет аутентифицированного пользователя на другой сервер django с той же БД - PullRequest
0 голосов
/ 15 октября 2019

Я знаю, вопрос звучит странно, я объясню здесь. У меня есть два сервера Django, которые совместно используют одну и ту же БД. Один из них - легкий передний / задний сервер, а второй - тяжелая вычислительная часть. Они совместно используют одну базу данных. В настоящее время я защищаю сеть, и у меня есть несколько представлений на сервере Light, требующих входа пользователя:

@login_required() 
@permission_required('auth.can_upload', login_url='/accounts/login/')

Это хорошо работает на сервере Light, поскольку пользователь аутентифицирован (request.user возвращает действительныйпользователь во взглядах).

Проблема возникает, когда мне приходится отправлять загруженные данные на другой сервер, так как он защищен, как я показал ранее, я не знаю, как передать его уже зарегистрированному пользователю (пользователь действителен, поскольку серверыподелиться БД).

# send an upload request using requests
s = requests.Session()

r1 = s.get(upload_process_url)
csrf_token = r1.cookies['csrftoken']
a = s.post(upload_process_url, files=request.FILES,
                   data={'csrfmiddlewaretoken': csrf_token},
                   headers=dict(Referer=upload_process_url))

Я не могу каждый раз спрашивать пользователя и пароль или сохранить их. Дело в том, что я хочу передать пользователю, который уже вошел в запрос.
Пользователь был зарегистрирован с использованием страницы django accounts/login по умолчанию и аутентификации.

Есть какие-нибудь подсказки и что я могу попробовать? Я думаю, что эта проблема не может быть такой сложной, как мне кажется. Я просто хочу отправить аутентифицированный запрос. Если я уберу декораторы, все прекрасно работает с этим кодом

Большое спасибо

1 Ответ

1 голос
/ 15 октября 2019

Посмотрите на REMOTE_USER-аутентификацию :

В этом документе описывается, как использовать внешние источники аутентификации (где веб-сервер устанавливает переменную среды REMOTE_USER) в вашем DjangoПриложения. Этот тип решения для проверки подлинности обычно встречается на сайтах интрасети с решениями с единым входом, такими как IIS и встроенная проверка подлинности Windows или Apache и mod_authnz_ldap, CAS, Cosign, WebAuth, mod_auth_sspi и т. Д.

В основномваш "легкий" сервер выполняет аутентификацию, как он уже делает. Когда вы делаете запрос к вашему «тяжелому» серверу, вы должны установить заголовок Auth-User, содержащий имя пользователя вашего пользователя. Затем Django автоматически аутентифицирует соответствующего пользователя.

По умолчанию Django считывает переменную среды, установленную сервером аутентификации. Но вместо этого мы можем заставить его работать с HTTP-заголовком:

# middlewares.py

from django.contrib.auth.middleware import RemoteUserMiddleware

class CustomHeaderMiddleware(RemoteUserMiddleware):
    header = 'HTTP_AUTH_USER'
# settings.py

MIDDLEWARE = [
    '...',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'my_project.middlewares.CustomHeaderMiddleware',
    '...',
]

Затем вы можете сделать что-то подобное в своем запросе (при условии, что у вас есть Django user под рукой):

s = requests.Session()

r1 = s.get(upload_process_url)
a = s.post(
    upload_process_url,
    files=request.FILES,
    headers={
        'Auth-User': user.username,
    },
)

Поскольку вы не выполняете запрос из браузера, вы можете избежать защиты от CSRF, пометив так называемое «тяжелое» представление с помощью декоратора @csrf_exempt (как вы сами обнаружили).

Будьте осторожны, чтобы ваш «тяжелый» сервер не был доступен напрямую через Интернет и всегда находился за прокси / VPN, доступным только вашему «легкому» серверу.

...