首页 > 解决方案 > Django 将经过身份验证的用户发送到具有相同数据库的另一个 django 服务器

问题描述

我知道这个问题听起来很奇怪,我会在这里解释一下。我有两个共享同一个数据库的 Django 服务器。一种是轻型前/后服务器,一种是重型计算部分。他们共享同一个数据库。我目前正在保护网络,我在轻型服务器中有几个需要用户登录的视图:

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

这在轻量级服务器中运行良好,因为用户已通过身份验证(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))

我不能每次都询问用户和密码或保存它们。问题是我想传递已经登录请求的用户。
用户是使用默认的 djangoaccounts/login页面和身份验证登录的。

任何线索,我可以尝试什么?我认为这个问题不可能像我认为的那样困难。我只想发送一个经过身份验证的请求。如果我删除装饰器,则此代码一切正常

非常感谢

标签: pythondjangodjango-rest-frameworkpython-requests

解决方案


看看REMOTE_USER 身份验证

本文档描述了如何在 Django 应用程序中使用外部身份验证源(Web 服务器在其中设置 REMOTE_USER 环境变量)。这种类型的身份验证解决方案通常出现在 Intranet 站点上,具有单点登录解决方案,例如 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',
    '...',
]

然后,您可以在您的请求中执行类似的操作(假设您user手头有 Django):

s = requests.Session()

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

由于您没有从浏览器发出请求,因此您可以通过使用@csrf_exempt装饰器标记所谓的“重”视图(正如您自己发现的那样)来避免 CSRF 保护。

请注意,您的“重型”服务器不应直接在 Internet 上访问,并且始终位于只能由“轻型”服务器访问的代理/VPN 后面。


推荐阅读