{"title":"使用 REMOTE_USER 进行身份验证","version":"6.0","locale":"zh-hans","docname":"howto/auth-remote-user","url":"/zh-hans/6.0/howto/auth-remote-user/","canonical":"https://djangodocs.dev/zh-hans/6.0/howto/auth-remote-user/","summary":"This document describes how to make use of external authentication sources in your Django applications. This type of authentication solution is typically seen on…","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>This document describes how to make use of external authentication sources in\nyour Django applications. This type of authentication solution is typically\nseen on intranet sites, with single sign-on solutions such as IIS and\nIntegrated Windows Authentication or Apache and <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>,\n<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>, etc.</p>\n<p>When the web server takes care of authentication it typically provides the\nauthenticated user as <code class=\"docutils literal notranslate\">REMOTE_USER</code>. In Django, this value is made available\nin <a class=\"reference internal\" href=\"/zh-hans/6.0/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> (as <code class=\"docutils literal notranslate\">REMOTE_USER</code> when\nsupplied as an environment variable, as in WSGI, or <code class=\"docutils literal notranslate\">HTTP_REMOTE_USER</code> when\nsupplied via an HTTP header, as in ASGI). Django can be configured to make use\nof the <code class=\"docutils literal notranslate\">REMOTE_USER</code> value using the <code class=\"docutils literal notranslate\">RemoteUserMiddleware</code> or\n<code class=\"docutils literal notranslate\">PersistentRemoteUserMiddleware</code>, and\n<a class=\"reference internal\" href=\"/zh-hans/6.0/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> classes found in\n<a class=\"reference internal\" href=\"/zh-hans/6.0/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>.</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/6.0/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\">MIDDLEWARE</code></a> 键中，在 <a class=\"reference internal\" href=\"/zh-hans/6.0/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/6.0/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/6.0/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/6.0/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/6.0/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>With this setup, <code class=\"docutils literal notranslate\">RemoteUserMiddleware</code> will detect the username in\n<code class=\"docutils literal notranslate\">request.META['REMOTE_USER']</code> (or <code class=\"docutils literal notranslate\">request.META['HTTP_REMOTE_USER']</code> under\nASGI) and will authenticate and auto-login that user\nusing the <a class=\"reference internal\" href=\"/zh-hans/6.0/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/6.0/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/6.0/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/6.0/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>如果你的认证机制使用自定义 HTTP 头而非 <code class=\"docutils literal notranslate\">REMOTE_USER</code>，你可以继承 <code class=\"docutils literal notranslate\">RemoteUserMiddleware</code> 并将 <code class=\"docutils literal notranslate\">header</code> 属性设为所需的 <code class=\"docutils literal notranslate\">request.META</code> 键名。例如：</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>这个自定义中间件随后将在 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\">MIDDLEWARE</code></a> 设置中替代 <a class=\"reference internal\" href=\"/zh-hans/6.0/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><code class=\"docutils literal notranslate\">RemoteUserMiddleware</code> must not be deployed in configurations where a\nclient can supply the header. You must be sure that your web server or\nreverse proxy always sets or strips that header based on the appropriate\nauthentication checks, never permitting an end user to submit a fake (or\n&quot;spoofed&quot;) header value.</p>\n<p>Since the HTTP headers <code class=\"docutils literal notranslate\">X-Auth-User</code> and <code class=\"docutils literal notranslate\">X-Auth_User</code> (for example)\nboth normalize to the <code class=\"docutils literal notranslate\">HTTP_X_AUTH_USER</code> key in <code class=\"docutils literal notranslate\">request.META</code>, you\nmust also check that your web server doesn't allow a spoofed header using\nunderscores in place of dashes.</p>\n<p>Under WSGI, this warning doesn't apply to <code class=\"docutils literal notranslate\">RemoteUserMiddleware</code> in its\ndefault configuration with <code class=\"docutils literal notranslate\">header = &quot;REMOTE_USER&quot;</code>, since a key that\ndoesn't start with <code class=\"docutils literal notranslate\">HTTP_</code> in <code class=\"docutils literal notranslate\">request.META</code> can only be set by your\nWSGI server, not directly from an HTTP request header.</p>\n<p>This warning applies under ASGI in all configurations, because there is\nno equivalent for a WSGI server's ability to place a trusted value in the\nenviron. ASGI deployments <em>must</em> use a reverse proxy as described above\nwhen using this middleware.</p>\n</aside>\n<p>如果你需要更多控制, 你可以通过继承 <a class=\"reference internal\" href=\"/zh-hans/6.0/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/6.0/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/6.0/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/6.0/howto/"}],"prev":{"docname":"howto/static-files/deployment","title":"如何部署静态文件","url":"/zh-hans/6.0/howto/static-files/deployment/"},"next":{"docname":"howto/csp","title":"如何使用 Django 的内容安全策略","url":"/zh-hans/6.0/howto/csp/"},"formats":{"html":"/zh-hans/6.0/howto/auth-remote-user/","markdown":"/zh-hans/6.0/howto/auth-remote-user.md","json":"/zh-hans/6.0/howto/auth-remote-user.json"},"source":"https://github.com/django/django/blob/stable/6.0.x/docs/howto/auth-remote-user.txt","official":"https://docs.djangoproject.com/zh-hans/6.0/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","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}