{"title":"使用 REMOTE_USER 进行身份验证","version":"2.1","locale":"zh-hans","docname":"howto/auth-remote-user","url":"/zh-hans/2.1/howto/auth-remote-user/","canonical":"https://djangodocs.dev/zh-hans/2.1/howto/auth-remote-user/","summary":"这篇文档讲述了如何在你的 Django 应用中使用外部身份验证资源(在web服务器上设置 `` REMOTE_USER``的地方)。这种类型的身份验证方法一般用在使用了单点登录方案的内部网站上，比如 IIS 和 Windows 一体化验证或者 Apache 和 mod_authnz_ldap , CAS , Cosign ,…","html":"<h1>使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">REMOTE_USER</span></code> 进行身份验证<a class=\"heading-anchor\" href=\"#authentication-using-remote-user\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>这篇文档讲述了如何在你的 Django 应用中使用外部身份验证资源(在web服务器上设置 <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>REMOTE_USER``的地方)。这种类型的身份验证方法一般用在使用了单点登录方案的内部网站上，比如 IIS 和 Windows 一体化验证或者 Apache 和 <a class=\"reference external\" href=\"https://httpd.apache.org/docs/2.2/mod/mod_authnz_ldap.html\">mod_authnz_ldap</a>, <a class=\"reference external\" href=\"https://www.apereo.org/projects/cas\">CAS</a>, <a class=\"reference external\" href=\"http://weblogin.org\">Cosign</a>, <a class=\"reference external\" href=\"https://www.stanford.edu/services/webauth/\">WebAuth</a>, <a href=\"#id3\"><span class=\"problematic\" id=\"id4\">`</span></a>mod_auth_sspi`_等等。</p>\n<p>当Web服务器负责鉴权时，通常设置``REMOTE_USER``这个环境变量为了在底层应用中使用。在Django中，<code class=\"docutils literal notranslate\"><span class=\"pre\">REMOTE_USER``是作为:attr:`request.META</span> <span class=\"pre\">&lt;django.http.HttpRequest.META&gt;` 的参数来使用的。如果想在Django中使用``REMOTE_USER</span></code>,  可以通过配置``RemoteUserMiddleware`` 中间件，<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>PersistentRemoteUserMiddleware``中间件，或者继承在  <code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.auth`中的:class:`~django.contrib.auth.backends.RemoteUserBackend</span></code> 来实现。</p>\n<section id=\"configuration\">\n<h2>配置<a class=\"heading-anchor\" href=\"#configuration\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>首先，你需要向配置文件的:setting:MIDDLEWARE`键中，在:class:`django.contrib.auth.middleware.AuthenticationMiddleware:: 的**后面**添加:class:django.contrib.auth.middleware.RemoteUserMiddleware :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">MIDDLEWARE</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"s1\">&#39;...&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.middleware.AuthenticationMiddleware&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.middleware.RemoteUserMiddleware&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;...&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>然后，你需要将设置中的:setting:AUTHENTICATION_BACKENDS setting:: 键值由:class:~django.contrib.auth.backends.ModelBackend  替换为:class:~django.contrib.auth.backends.RemoteUserBackend</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">AUTHENTICATION_BACKENDS</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"s1\">&#39;django.contrib.auth.backends.RemoteUserBackend&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>通过此项设置， <code class=\"docutils literal notranslate\"><span class=\"pre\">RemoteUserMiddleware</span></code> 可以检测``request.META['REMOTE_USER']`` 中的用户名，而且可以认证和自动登录用户使用的:class:~django.contrib.auth.backends.RemoteUserBackend.</p>\n<p>要注意这项设置将导致无法使用默认的``ModelBackend``验证。也就是说如果``REMOTE_USER``的值没有指定则该用户将无法登录，即使通过Django的管理后台。要解决这些问题，把``'django.contrib.auth.backends.ModelBackend'<code class=\"docutils literal notranslate\"><span class=\"pre\">加入``AUTHENTICATION_BACKENDS``列表中，则当``REMOTE_USER``未指定时，就会回退使用``ModelBackend</span></code>。</p>\n<p>Django的用户管理系统，比如``contrib.admin``中的视图函数及:djadmin:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>createsuperuser`的管理命令，都没有与远程用户集成。这些接口只工作在数据库中存储的用户上，无论``AUTHENTICATION_BACKENDS``为何值。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>因为 <code class=\"docutils literal notranslate\"><span class=\"pre\">RemoteUserBackend</span></code> 继承自 <code class=\"docutils literal notranslate\"><span class=\"pre\">ModelBackend</span></code>, 您仍将拥有在  <code class=\"docutils literal notranslate\"><span class=\"pre\">ModelBackend</span></code> 中实现的所有相同的权限检查。</p>\n<p>具有:attr:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>is_active=False &lt;django.contrib.auth.models.User.is_active&gt;`的用户将被禁止验证。你可以使用:class:<a href=\"#id3\"><span class=\"problematic\" id=\"id4\">`</span></a>~django.contrib.auth.backends.AllowAllUsersRemoteUserBackend`来允许验证。</p>\n</aside>\n<p>如果你的验证机制使用一个自定义的HTTP头部而不是``REMOTE_USER``，你可以构建一个``RemoteUserMiddleWare``的子类然后把``header``属性设成你希望的``request.META``键值。例如:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.middleware</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">RemoteUserMiddleware</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">CustomHeaderMiddleware</span><span class=\"p\">(</span><span class=\"n\">RemoteUserMiddleware</span><span class=\"p\">):</span>\n    <span class=\"n\">header</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;HTTP_AUTHUSER&#39;</span>\n</code></pre></div>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>使用具有自定义HTTP头部的``RemoteUserMiddleware``子类时需要特别小心。你要确保你的前端服务器基于验证检查结果正确设置或去除了该头部，禁止任何终端用户提交一个仿冒的头部值。因为HTTP头部``X-Auth-User``与（比方说）``X-Auth_User``都会标准化为``request.META``的``HTTP_X_AUTH_USER``键，你必须确保你的服务器不允许头部使用下划线来替代横杠。</p>\n<p>这个警告不适用于 <code class=\"docutils literal notranslate\"><span class=\"pre\">RemoteUserMiddlewar</span></code>，它的默认配置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">header</span> <span class=\"pre\">='REMOTE_USER'</span></code>, 因为在 <code class=\"docutils literal notranslate\"><span class=\"pre\">request.META</span></code> 中不存在以 <code class=\"docutils literal notranslate\"><span class=\"pre\">HTTP_</span></code> 开始的键可以只由WSGI服务器设置, 而不能直接来自HTTP请求头部.</p>\n</aside>\n<p>如果你需要更多控制, 你可以通过继承 <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/contrib/auth/#django.contrib.auth.backends.RemoteUserBackend\" title=\"django.contrib.auth.backends.RemoteUserBackend\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RemoteUserBackend</span></code></a>  并且覆盖其一个或多个属性和方法来创建你自己的验证后端.</p>\n</section>\n<section id=\"using-remote-user-on-login-pages-only\">\n<span id=\"persistent-remote-user-middleware-howto\"></span><h2>仅在登录界面使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">REMOTE_USER</span></code><a class=\"heading-anchor\" href=\"#using-remote-user-on-login-pages-only\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p><a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>RemoteUserMiddleware``验证中间件假定所有已验证的请求都包含``REMOTE_USER``头部。这可能对于使用``htpasswd``或其他简单机制的基础HTTP验证方式是很自然的，然而对于协商验证（GSSAP/Kerberos）或其他资源密集的验证方式来说，前端HTTP服务器的验证通常只在几个登录的URL上存在，在验证成功之后，应用需要自己维护已验证的会话。</p>\n<p><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RemoteUserMiddleware</span></code>。</p>\n</section>","rootId":"authentication-using-remote-user","toc":[{"title":"配置","anchor":"configuration","children":[]},{"title":"仅在登录界面使用 REMOTE_USER","anchor":"using-remote-user-on-login-pages-only","children":[]}],"breadcrumbs":[{"docname":"howto/index","title":"\"How-to\" guides","url":"/zh-hans/2.1/howto/"}],"prev":{"docname":"howto/index","title":"\"How-to\" guides","url":"/zh-hans/2.1/howto/"},"next":{"docname":"howto/custom-management-commands","title":"编写自定义 django-admin 的命令","url":"/zh-hans/2.1/howto/custom-management-commands/"},"formats":{"html":"/zh-hans/2.1/howto/auth-remote-user/","markdown":"/zh-hans/2.1/howto/auth-remote-user.md","json":"/zh-hans/2.1/howto/auth-remote-user.json"},"source":"https://github.com/django/django/blob/stable/2.1.x/docs/howto/auth-remote-user.txt","official":"https://docs.djangoproject.com/zh-hans/2.1/howto/auth-remote-user/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0"],"inLocales":["en","zh-hans","fr","ja","id","pt-br","ko","es","el","pl"]}