本文介绍如何在 Django 应用中使用外部身份验证来源。这类身份验证方案通常用于内网站点,例如 IIS 与 Windows 集成身份验证,或者 Apache 配合 mod_authnz_ldap、CAS、WebAuth、mod_auth_sspi 等单点登录方案。
当 Web 服务器负责身份验证时,通常会通过 REMOTE_USER 提供已验证用户的身份。在 Django 中,可以通过 request.META 访问这个值:像 WSGI 那样由环境变量提供时,键名为 REMOTE_USER;像 ASGI 那样通过 HTTP 请求头提供时,键名为 HTTP_REMOTE_USER。可以配置 Django,使用 django.contrib.auth 中的 RemoteUserMiddleware 或 PersistentRemoteUserMiddleware,以及 RemoteUserBackend 类,利用 REMOTE_USER 的值完成验证。
配置
首先,你需要向配置文件的 MIDDLEWARE 键中,在 django.contrib.auth.middleware.AuthenticationMiddleware 的 后面 添加 django.contrib.auth.middleware.RemoteUserMiddleware:
MIDDLEWARE = [
"...",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.auth.middleware.RemoteUserMiddleware",
"...",
]
然后,将 AUTHENTICATION_BACKENDS 设置中的 ModelBackend 替换为 RemoteUserBackend:
AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.RemoteUserBackend",
]
完成上述配置后,RemoteUserMiddleware 会从 request.META['REMOTE_USER'] 中检测用户名;在 ASGI 环境中,则读取 request.META['HTTP_REMOTE_USER']。随后,中间件会使用 RemoteUserBackend 验证该用户并自动登录。
要注意这项设置将导致无法使用默认的 ModelBackend 验证。也就是说如果 REMOTE_USER 的值没有指定则该用户将无法登录,即使通过 Django 的管理后台。要解决这些问题,把 'django.contrib.auth.backends.ModelBackend' 加入 AUTHENTICATION_BACKENDS 列表中,则当 REMOTE_USER 未指定时,就会回退使用 ModelBackend。
Django 的用户管理系统,比如 contrib.admin 中的视图函数及 createsuperuser 的管理命令,都没有与远程用户集成。这些接口只工作在数据库中存储的用户上,无论 AUTHENTICATION_BACKENDS 为何值。
说明
因为 RemoteUserBackend 继承自 ModelBackend, 您仍将拥有在 ModelBackend 中实现的所有相同的权限检查。
具有 is_active=False 的用户将被禁止验证。你可以使用 AllowAllUsersRemoteUserBackend 来允许验证。
如果你的认证机制使用自定义 HTTP 头而非 REMOTE_USER,你可以继承 RemoteUserMiddleware 并将 header 属性设为所需的 request.META 键名。例如:
mysite/middleware.py from django.contrib.auth.middleware import RemoteUserMiddleware
class CustomHeaderRemoteUserMiddleware(RemoteUserMiddleware):
header = "HTTP_AUTHUSER"
这个自定义中间件随后将在 MIDDLEWARE 设置中替代 django.contrib.auth.middleware.RemoteUserMiddleware 被使用:
MIDDLEWARE = [
"...",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"mysite.middleware.CustomHeaderRemoteUserMiddleware",
"...",
]
警告
不能在客户端可以自行提供该请求头的配置中部署 RemoteUserMiddleware。必须确保 Web 服务器或反向代理始终根据相应的身份验证结果设置或移除这个请求头,绝不能允许最终用户提交伪造的请求头值。
例如,HTTP 请求头 X-Auth-User 和 X-Auth_User 都会被规范化为 request.META 中的 HTTP_X_AUTH_USER 键。因此,还必须确认 Web 服务器不会放行通过下划线替代连字符而伪造的请求头。
在 WSGI 环境中,如果 RemoteUserMiddleware 使用默认配置 header = "REMOTE_USER",则不受这项警告影响。原因是 request.META 中不以 HTTP_ 开头的键只能由 WSGI 服务器设置,不能直接来自 HTTP 请求头。
在 ASGI 环境中,这项警告适用于所有配置,因为 ASGI 没有与 WSGI 服务器向环境中写入可信值等效的机制。在 ASGI 部署中使用这个中间件时,必须按上文说明使用反向代理。
如果你需要更多控制, 你可以通过继承 RemoteUserBackend 并且覆盖其一个或多个属性和方法来创建你自己的验证后端.
仅在登录界面使用 REMOTE_USER
RemoteUserMiddleware 假定每个已验证请求都包含 REMOTE_USER。使用 htpasswd 或类似机制进行 HTTP Basic 身份验证时,这个假定是合理的;但使用 Negotiate(GSSAPI/Kerberos)或其他资源开销较大的验证方式时,前端 HTTP 服务器通常只在一个或少数几个登录 URL 上执行验证,验证成功后需要由应用自行维护会话。
PersistentRemoteUserMiddleware 就针对这个使用场景提供了支持。除非用户显式地退出登录,它将一直保留已认证的会话。这个中间件可以代替上文中的 RemoteUserMiddleware。
原文:使用 REMOTE_USER 进行身份验证。作者/来源:Django 项目与文档贡献者。本文依据所列原文整理为中文,代码、命令与配置示例保留原文。











暂无评论内容