使用 REMOTE_USER
进行身份验证
本文档描述如何在 Django 应用中使用外部身份验证资源(在 web 服务器上设置 REMOTE_USER
环境变量的地方)。这种类型的身份验证方法一般用在使用了单点登录方案的内部网站上,比如 IIS 和 Windows 一体化验证或者 Apache 和 mod_authnz_ldap, CAS, Cosign, 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
为何值。
注解
因为 RemoteUserBackend
继承自 ModelBackend
, 您仍将拥有在 ModelBackend
中实现的所有相同的权限检查。
具有 is_active=False
的用户将被禁止验证。你可以使用 AllowAllUsersRemoteUserBackend
来允许验证。
如果你的验证机制使用一个自定义的 HTTP header 而不是 REMOTE_USER
,你可以构建一个 RemoteUserMiddleWare
的子类然后把 header
属性设成你希望的 request.META
键值。例如:
from django.contrib.auth.middleware import RemoteUserMiddleware
class CustomHeaderMiddleware(RemoteUserMiddleware):
header = 'HTTP_AUTHUSER'
警告
使用具有自定义HTTP头部的 RemoteUserMiddleware
子类时需要特别小心。你要确保你的前端服务器基于验证检查结果正确设置或去除了该头部,禁止任何终端用户提交一个仿冒的头部值。因为HTTP头部 X-Auth-User
与(比方说) X-Auth_User
都会标准化为 request.META
的 HTTP_X_AUTH_USER
键,你必须确保你的服务器不允许头部使用下划线来替代横杠。
这个警告不适用于 RemoteUserMiddlewar
,它的默认配置为 header ='REMOTE_USER'
, 因为在 request.META
中不存在以 HTTP_
开始的键可以只由WSGI服务器设置, 而不能直接来自HTTP请求头部.
如果你需要更多控制, 你可以通过继承 RemoteUserBackend
并且覆盖其一个或多个属性和方法来创建你自己的验证后端.
仅在登录界面使用 REMOTE_USER
RemoteUserMiddleware
这个认证中间件 ,它假设HTTP请求的头部 REMOTE_USER
在所有认证请求中都存在。这个假设在当通过 htpasswd
或者相似的认证机制来做Basic HTTP的认证时才是可行的,但是使用Negotiate (GSSAPI/Kerberos) 或者其它资源密集型的认证方法时就说不过去了,前端HTTP server的认证通常用在仅仅一个或不太多的登录URLs,而且在认证成功后,应用还要自己去维护这个session。
PersistentRemoteUserMiddleware
就针对这个使用场景提供了支持。除非用户显式地退出登录,它将一直保留已认证的会话。这个中间件可以代替上文中的 RemoteUserMiddleware
。