{"title":"使用 REMOTE_USER 进行身份验证","version":"5.1","locale":"zh-hans","docname":"howto/auth-remote-user","url":"/zh-hans/5.1/howto/auth-remote-user/","canonical":"https://djangodocs.dev/zh-hans/5.1/howto/auth-remote-user/","summary":"本文档描述了如何在 Django 应用程序中使用外部身份验证源（Web 服务器设置 REMOTE_USER 环境变量）。此类身份验证解决方案通常在 intranet 网站上看到，具有单点登录解决方案，如 IIS 和集成 Windows 身份验证或 Apache 和 mod_authnz_ldap 、 CAS 、 WebAuth…","html":"<h1>使用 <code class=\"docutils literal notranslate\">REMOTE_USER</code> 进行身份验证<a class=\"heading-anchor\" href=\"#how-to-authenticate-using-remote-user\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>本文档描述了如何在 Django 应用程序中使用外部身份验证源（Web 服务器设置 <code class=\"docutils literal notranslate\">REMOTE_USER</code> 环境变量）。此类身份验证解决方案通常在 intranet 网站上看到，具有单点登录解决方案，如 IIS 和集成 Windows 身份验证或 Apache 和 <a class=\"reference external\" href=\"https://httpd.apache.org/docs/current/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=\"https://uit.stanford.edu/service/authentication\">WebAuth</a>、<a class=\"reference external\" href=\"https://sourceforge.net/projects/mod-auth-sspi\">mod_auth_sspi</a> 等。</p>\n<p>当 Web 服务器负责鉴权时，通常会设置 <code class=\"docutils literal notranslate\">REMOTE_USER</code> 环境变量，这是为了在底层应用中使用。在 Django 中， <code class=\"docutils literal notranslate\">REMOTE_USER</code> 是作为 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/request-response/#django.http.HttpRequest.META\" title=\"django.http.HttpRequest.META\"><code class=\"xref py py-attr docutils literal notranslate\">request.META</code></a> 的参数来使用的。如果想在 Django 中使用 <code class=\"docutils literal notranslate\">REMOTE_USER</code>, 可以通过配置 <code class=\"docutils literal notranslate\">RemoteUserMiddleware</code> 中间件， <code class=\"docutils literal notranslate\">PersistentRemoteUserMiddleware</code> 中间件，或者继承在 <a class=\"reference internal\" href=\"/zh-hans/5.1/topics/auth/#module-django.contrib.auth\" title=\"django.contrib.auth: Django's authentication framework.\"><code class=\"xref py py-mod docutils literal notranslate\">django.contrib.auth</code></a> 中的 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/contrib/auth/#django.contrib.auth.backends.RemoteUserBackend\" title=\"django.contrib.auth.backends.RemoteUserBackend\"><code class=\"xref py py-class docutils literal notranslate\">RemoteUserBackend</code></a> 来实现。</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>首先，你需要向配置文件的 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\">MIDDLEWARE</code></a> 键中，在 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/middleware/#django.contrib.auth.middleware.AuthenticationMiddleware\" title=\"django.contrib.auth.middleware.AuthenticationMiddleware\"><code class=\"xref py py-class docutils literal notranslate\">django.contrib.auth.middleware.AuthenticationMiddleware</code></a> 的 <strong>后面</strong> 添加 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/middleware/#django.contrib.auth.middleware.RemoteUserMiddleware\" title=\"django.contrib.auth.middleware.RemoteUserMiddleware\"><code class=\"xref py py-class docutils literal notranslate\">django.contrib.auth.middleware.RemoteUserMiddleware</code></a></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>MIDDLEWARE <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"s2\">&quot;...&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.middleware.AuthenticationMiddleware&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.middleware.RemoteUserMiddleware&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;...&quot;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>然后，你需要将设置中的 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-AUTHENTICATION_BACKENDS\"><code class=\"xref std std-setting docutils literal notranslate\">AUTHENTICATION_BACKENDS</code></a> setting:: 键值由 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/contrib/auth/#django.contrib.auth.backends.ModelBackend\" title=\"django.contrib.auth.backends.ModelBackend\"><code class=\"xref py py-class docutils literal notranslate\">ModelBackend</code></a> 替换为 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/contrib/auth/#django.contrib.auth.backends.RemoteUserBackend\" title=\"django.contrib.auth.backends.RemoteUserBackend\"><code class=\"xref py py-class docutils literal notranslate\">RemoteUserBackend</code></a>:</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>AUTHENTICATION_BACKENDS <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"s2\">&quot;django.contrib.auth.backends.RemoteUserBackend&quot;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>通过此项设置， <code class=\"docutils literal notranslate\">RemoteUserMiddleware</code> 可以检测 <code class=\"docutils literal notranslate\">request.META['REMOTE_USER']</code> 中的用户名，而且可以认证和自动登录用户使用的 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/contrib/auth/#django.contrib.auth.backends.RemoteUserBackend\" title=\"django.contrib.auth.backends.RemoteUserBackend\"><code class=\"xref py py-class docutils literal notranslate\">RemoteUserBackend</code></a>。</p>\n<p>要注意这项设置将导致无法使用默认的 <code class=\"docutils literal notranslate\">ModelBackend</code> 验证。也就是说如果 <code class=\"docutils literal notranslate\">REMOTE_USER</code> 的值没有指定则该用户将无法登录，即使通过 Django 的管理后台。要解决这些问题，把 <code class=\"docutils literal notranslate\">'django.contrib.auth.backends.ModelBackend'</code> 加入 <code class=\"docutils literal notranslate\">AUTHENTICATION_BACKENDS</code> 列表中，则当 <code class=\"docutils literal notranslate\">REMOTE_USER</code> 未指定时，就会回退使用 <code class=\"docutils literal notranslate\">ModelBackend</code>。</p>\n<p>Django 的用户管理系统，比如 <code class=\"docutils literal notranslate\">contrib.admin</code> 中的视图函数及 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/django-admin/#django-admin-createsuperuser\"><code class=\"xref std std-djadmin docutils literal notranslate\">createsuperuser</code></a> 的管理命令，都没有与远程用户集成。这些接口只工作在数据库中存储的用户上，无论 <code class=\"docutils literal notranslate\">AUTHENTICATION_BACKENDS</code> 为何值。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>因为 <code class=\"docutils literal notranslate\">RemoteUserBackend</code> 继承自 <code class=\"docutils literal notranslate\">ModelBackend</code>, 您仍将拥有在  <code class=\"docutils literal notranslate\">ModelBackend</code> 中实现的所有相同的权限检查。</p>\n<p>具有 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/contrib/auth/#django.contrib.auth.models.User.is_active\" title=\"django.contrib.auth.models.User.is_active\"><code class=\"xref py py-attr docutils literal notranslate\">is_active=False</code></a> 的用户将被禁止验证。你可以使用 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/contrib/auth/#django.contrib.auth.backends.AllowAllUsersRemoteUserBackend\" title=\"django.contrib.auth.backends.AllowAllUsersRemoteUserBackend\"><code class=\"xref py py-class docutils literal notranslate\">AllowAllUsersRemoteUserBackend</code></a> 来允许验证。</p>\n</aside>\n<p>If your authentication mechanism uses a custom HTTP header and not\n<code class=\"docutils literal notranslate\">REMOTE_USER</code>, you can subclass <code class=\"docutils literal notranslate\">RemoteUserMiddleware</code> and set the\n<code class=\"docutils literal notranslate\">header</code> attribute to the desired <code class=\"docutils literal notranslate\">request.META</code> key.  For example:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\">mysite/middleware.py</code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</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=\"Python code\"><code> <span class=\"kn\">from</span> <span class=\"nn\">django.contrib.auth.middleware</span> <span class=\"kn\">import</span> RemoteUserMiddleware\n\n\n <span class=\"k\">class</span> <span class=\"nc\">CustomHeaderRemoteUserMiddleware</span><span class=\"p\">(</span>RemoteUserMiddleware<span class=\"p\">):</span>\n     header <span class=\"o\">=</span> <span class=\"s2\">&quot;HTTP_AUTHUSER&quot;</span>\n</code></pre></figure>\n<p>This custom middleware is then used in the <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\">MIDDLEWARE</code></a> setting\ninstead of <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/middleware/#django.contrib.auth.middleware.RemoteUserMiddleware\" title=\"django.contrib.auth.middleware.RemoteUserMiddleware\"><code class=\"xref py py-class docutils literal notranslate\">django.contrib.auth.middleware.RemoteUserMiddleware</code></a>:</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>MIDDLEWARE <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"s2\">&quot;...&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.middleware.AuthenticationMiddleware&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;mysite.middleware.CustomHeaderRemoteUserMiddleware&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;...&quot;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>使用具有自定义HTTP头部的 <code class=\"docutils literal notranslate\">RemoteUserMiddleware</code> 子类时需要特别小心。你要确保你的前端服务器基于验证检查结果正确设置或去除了该头部，禁止任何终端用户提交一个仿冒的头部值。因为HTTP头部 <code class=\"docutils literal notranslate\">X-Auth-User</code> 与（比方说） <code class=\"docutils literal notranslate\">X-Auth_User</code> 都会标准化为 <code class=\"docutils literal notranslate\">request.META</code> 的 <code class=\"docutils literal notranslate\">HTTP_X_AUTH_USER</code> 键，你必须确保你的服务器不允许头部使用下划线来替代横杠。</p>\n<p>这个警告不适用于 <code class=\"docutils literal notranslate\">RemoteUserMiddlewar</code>，它的默认配置为 <code class=\"docutils literal notranslate\">header ='REMOTE_USER'</code>, 因为在 <code class=\"docutils literal notranslate\">request.META</code> 中不存在以 <code class=\"docutils literal notranslate\">HTTP_</code> 开始的键可以只由WSGI服务器设置, 而不能直接来自HTTP请求头部.</p>\n</aside>\n<p>如果你需要更多控制, 你可以通过继承 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/contrib/auth/#django.contrib.auth.backends.RemoteUserBackend\" title=\"django.contrib.auth.backends.RemoteUserBackend\"><code class=\"xref py py-class docutils literal notranslate\">RemoteUserBackend</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\">REMOTE_USER</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><code class=\"docutils literal notranslate\">RemoteUserMiddleware</code> 这个认证中间件 ，它假设HTTP请求的头部 <code class=\"docutils literal notranslate\">REMOTE_USER</code> 在所有认证请求中都存在。这个假设在当通过 <code class=\"docutils literal notranslate\">htpasswd</code> 或者相似的认证机制来做Basic HTTP的认证时才是可行的，但是使用Negotiate (GSSAPI/Kerberos) 或者其它资源密集型的认证方法时就说不过去了，前端HTTP server的认证通常用在仅仅一个或不太多的登录URLs，而且在认证成功后，应用还要自己去维护这个session。</p>\n<p><a class=\"reference internal\" href=\"/zh-hans/5.1/ref/middleware/#django.contrib.auth.middleware.PersistentRemoteUserMiddleware\" title=\"django.contrib.auth.middleware.PersistentRemoteUserMiddleware\"><code class=\"xref py py-class docutils literal notranslate\">PersistentRemoteUserMiddleware</code></a> 就针对这个使用场景提供了支持。除非用户显式地退出登录，它将一直保留已认证的会话。这个中间件可以代替上文中的 <a class=\"reference internal\" href=\"/zh-hans/5.1/ref/middleware/#django.contrib.auth.middleware.RemoteUserMiddleware\" title=\"django.contrib.auth.middleware.RemoteUserMiddleware\"><code class=\"xref py py-class docutils literal notranslate\">RemoteUserMiddleware</code></a>。</p>\n</section>","rootId":"how-to-authenticate-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":"如何引导","url":"/zh-hans/5.1/howto/"}],"prev":{"docname":"howto/static-files/deployment","title":"如何部署静态文件","url":"/zh-hans/5.1/howto/static-files/deployment/"},"next":{"docname":"howto/csrf","title":"如何使用 Django 提供的 CSRF 防护功能","url":"/zh-hans/5.1/howto/csrf/"},"formats":{"html":"/zh-hans/5.1/howto/auth-remote-user/","markdown":"/zh-hans/5.1/howto/auth-remote-user.md","json":"/zh-hans/5.1/howto/auth-remote-user.json"},"source":"https://github.com/django/django/blob/stable/5.1.x/docs/howto/auth-remote-user.txt","official":"https://docs.djangoproject.com/zh-hans/5.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","it","pt-br","ko","es","el","pl"]}