使用 REMOTE_USER 进行身份验证¶
本文档描述了如何在 Django 应用程序中使用外部身份验证源(Web 服务器设置 REMOTE_USER 环境变量)。此类身份验证解决方案通常在 intranet 网站上看到,具有单点登录解决方案,如 IIS 和集成 Windows 身份验证或 Apache 和 mod_authnz_ldap、CAS、WebAuth、mod_auth_sspi 等。
当 Web 服务器负责鉴权时,通常会设置 REMOTE_USER 环境变量,这是为了在底层应用中使用。在 Django 中, REMOTE_USER 是作为 request.META 的参数来使用的。如果想在 Django 中使用 REMOTE_USER, 可以通过配置 RemoteUserMiddleware 中间件, PersistentRemoteUserMiddleware 中间件,或者继承在 django.contrib.auth 中的 RemoteUserBackend 来实现。
配置¶
首先,你需要向配置文件的 MIDDLEWARE 键中,在 django.contrib.auth.middleware.AuthenticationMiddleware 的 后面 添加 django.contrib.auth.middleware.RemoteUserMiddleware:
MIDDLEWARE = [
"...",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.auth.middleware.RemoteUserMiddleware",
"...",
]
然后,你需要将设置中的 AUTHENTICATION_BACKENDS setting 键值由 ModelBackend 替换为 RemoteUserBackend:
AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.RemoteUserBackend",
]
通过此项设置, RemoteUserMiddleware 可以检测 request.META['REMOTE_USER'] 中的用户名,而且可以认证和自动登录用户使用的 RemoteUserBackend。
要注意这项设置将导致无法使用默认的 ModelBackend 验证。也就是说如果 REMOTE_USER 的值没有指定则该用户将无法登录,即使通过 Django 的管理后台。要解决这些问题,把 'django.contrib.auth.backends.ModelBackend' 加入 AUTHENTICATION_BACKENDS 列表中,则当 REMOTE_USER 未指定时,就会回退使用 ModelBackend。
Django 的用户管理系统,比如 contrib.admin 中的视图函数及 createsuperuser 的管理命令,都没有与远程用户集成。这些接口只工作在数据库中存储的用户上,无论 AUTHENTICATION_BACKENDS 为何值。
Note
因为 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",
"...",
]
Warning
RemoteUserMiddleware must not be deployed in configurations where a
client can supply the header. You must be sure that your web server or
reverse proxy always sets or strips that header based on the appropriate
authentication checks, never permitting an end user to submit a fake (or
"spoofed") header value. In particular, ASGI deployments cannot be exposed
directly to the internet (that is, without a reverse proxy) when using this
middleware.
Since the HTTP headers X-Auth-User and X-Auth_User (for example)
both normalize to the HTTP_X_AUTH_USER key in request.META, you
must also check that your web server doesn't allow a spoofed header using
underscores in place of dashes.
Under WSGI, this warning doesn't apply to RemoteUserMiddleware in its
default configuration with header = "REMOTE_USER", since a key that
doesn't start with HTTP_ in request.META can only be set by your
WSGI server, not directly from an HTTP request header. This warning does
apply by default on ASGI, because in the async path, the middleware
prepends HTTP_ to the defined header name before looking it up in
request.META.
如果你需要更多控制, 你可以通过继承 RemoteUserBackend 并且覆盖其一个或多个属性和方法来创建你自己的验证后端.
仅在登录界面使用 REMOTE_USER¶
RemoteUserMiddleware 这个认证中间件 ,它假设HTTP请求的头部 REMOTE_USER 在所有认证请求中都存在。这个假设在当通过 htpasswd 或者相似的认证机制来做Basic HTTP的认证时才是可行的,但是使用Negotiate (GSSAPI/Kerberos) 或者其它资源密集型的认证方法时就说不过去了,前端HTTP server的认证通常用在仅仅一个或不太多的登录URLs,而且在认证成功后,应用还要自己去维护这个session。
PersistentRemoteUserMiddleware 就针对这个使用场景提供了支持。除非用户显式地退出登录,它将一直保留已认证的会话。这个中间件可以代替上文中的 RemoteUserMiddleware。