{"title":"使用 REMOTE_USER 进行身份验证","version":"6.1","locale":"zh-hans","docname":"howto/auth-remote-user","url":"/zh-hans/6.1/howto/auth-remote-user/","canonical":"https://djangodocs.dev/zh-hans/6.1/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\"><span class=\"pre\">REMOTE_USER</span></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\"><span class=\"pre\">REMOTE_USER</span></code>. In Django, this value is made available\nin <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/request-response/#django.http.HttpRequest.META\" title=\"django.http.HttpRequest.META\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">request.META</span></code></a> (as <code class=\"docutils literal notranslate\"><span class=\"pre\">REMOTE_USER</span></code> when\nsupplied as an environment variable, as in WSGI, or <code class=\"docutils literal notranslate\"><span class=\"pre\">HTTP_REMOTE_USER</span></code> when\nsupplied via an HTTP header, as in ASGI). Django can be configured to make use\nof the <code class=\"docutils literal notranslate\"><span class=\"pre\">REMOTE_USER</span></code> value using the <code class=\"docutils literal notranslate\"><span class=\"pre\">RemoteUserMiddleware</span></code> or\n<code class=\"docutils literal notranslate\"><span class=\"pre\">PersistentRemoteUserMiddleware</span></code>, and\n<a class=\"reference internal\" href=\"/zh-hans/6.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> classes found in\n<a class=\"reference internal\" href=\"/zh-hans/6.1/topics/auth/#module-django.contrib.auth\" title=\"django.contrib.auth: Django's authentication framework.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.auth</span></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.1/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE</span></code></a> 键中，在 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/middleware/#django.contrib.auth.middleware.AuthenticationMiddleware\" title=\"django.contrib.auth.middleware.AuthenticationMiddleware\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.middleware.AuthenticationMiddleware</span></code></a> 的 <strong>后面</strong> 添加 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/middleware/#django.contrib.auth.middleware.RemoteUserMiddleware\" title=\"django.contrib.auth.middleware.RemoteUserMiddleware\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.middleware.RemoteUserMiddleware</span></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><span class=\"n\">MIDDLEWARE</span> <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.1/ref/settings/#std-setting-AUTHENTICATION_BACKENDS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTHENTICATION_BACKENDS</span></code></a> setting 键值由 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/contrib/auth/#django.contrib.auth.backends.ModelBackend\" title=\"django.contrib.auth.backends.ModelBackend\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ModelBackend</span></code></a> 替换为 <a class=\"reference internal\" href=\"/zh-hans/6.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<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=\"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\"><span class=\"pre\">RemoteUserMiddleware</span></code> will detect the username in\n<code class=\"docutils literal notranslate\"><span class=\"pre\">request.META['REMOTE_USER']</span></code> (or <code class=\"docutils literal notranslate\"><span class=\"pre\">request.META['HTTP_REMOTE_USER']</span></code> under\nASGI) and will authenticate and auto-login that user\nusing the <a class=\"reference internal\" href=\"/zh-hans/6.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<p>要注意这项设置将导致无法使用默认的 <code class=\"docutils literal notranslate\"><span class=\"pre\">ModelBackend</span></code> 验证。也就是说如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">REMOTE_USER</span></code> 的值没有指定则该用户将无法登录，即使通过 Django 的管理后台。要解决这些问题，把 <code class=\"docutils literal notranslate\"><span class=\"pre\">'django.contrib.auth.backends.ModelBackend'</span></code> 加入 <code class=\"docutils literal notranslate\"><span class=\"pre\">AUTHENTICATION_BACKENDS</span></code> 列表中，则当 <code class=\"docutils literal notranslate\"><span class=\"pre\">REMOTE_USER</span></code> 未指定时，就会回退使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">ModelBackend</span></code>。</p>\n<p>Django 的用户管理系统，比如 <code class=\"docutils literal notranslate\"><span class=\"pre\">contrib.admin</span></code> 中的视图函数及 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/django-admin/#django-admin-createsuperuser\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">createsuperuser</span></code></a> 的管理命令，都没有与远程用户集成。这些接口只工作在数据库中存储的用户上，无论 <code class=\"docutils literal notranslate\"><span class=\"pre\">AUTHENTICATION_BACKENDS</span></code> 为何值。</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>具有 <a class=\"reference internal\" href=\"/zh-hans/6.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\"><span class=\"pre\">is_active=False</span></code></a> 的用户将被禁止验证。你可以使用 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/contrib/auth/#django.contrib.auth.backends.AllowAllUsersRemoteUserBackend\" title=\"django.contrib.auth.backends.AllowAllUsersRemoteUserBackend\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AllowAllUsersRemoteUserBackend</span></code></a> 来允许验证。</p>\n</aside>\n<p>如果你的认证机制使用自定义 HTTP 头而非 <code class=\"docutils literal notranslate\"><span class=\"pre\">REMOTE_USER</span></code>，你可以继承 <code class=\"docutils literal notranslate\"><span class=\"pre\">RemoteUserMiddleware</span></code> 并将 <code class=\"docutils literal notranslate\"><span class=\"pre\">header</span></code> 属性设为所需的 <code class=\"docutils literal notranslate\"><span class=\"pre\">request.META</span></code> 键名。例如：</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">mysite/middleware.py</span></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=\"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\n <span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">CustomHeaderRemoteUserMiddleware</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=\"s2\">&quot;HTTP_AUTHUSER&quot;</span>\n</code></pre></figure>\n<p>这个自定义中间件随后将在 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE</span></code></a> 设置中替代 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/middleware/#django.contrib.auth.middleware.RemoteUserMiddleware\" title=\"django.contrib.auth.middleware.RemoteUserMiddleware\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.middleware.RemoteUserMiddleware</span></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><span class=\"n\">MIDDLEWARE</span> <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\"><span class=\"pre\">RemoteUserMiddleware</span></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\"><span class=\"pre\">X-Auth-User</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">X-Auth_User</span></code> (for example)\nboth normalize to the <code class=\"docutils literal notranslate\"><span class=\"pre\">HTTP_X_AUTH_USER</span></code> key in <code class=\"docutils literal notranslate\"><span class=\"pre\">request.META</span></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\"><span class=\"pre\">RemoteUserMiddleware</span></code> in its\ndefault configuration with <code class=\"docutils literal notranslate\"><span class=\"pre\">header</span> <span class=\"pre\">=</span> <span class=\"pre\">&quot;REMOTE_USER&quot;</span></code>, since a key that\ndoesn't start with <code class=\"docutils literal notranslate\"><span class=\"pre\">HTTP_</span></code> in <code class=\"docutils literal notranslate\"><span class=\"pre\">request.META</span></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.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><code class=\"docutils literal notranslate\"><span class=\"pre\">RemoteUserMiddleware</span></code> 这个认证中间件 ，它假设HTTP请求的头部 <code class=\"docutils literal notranslate\"><span class=\"pre\">REMOTE_USER</span></code> 在所有认证请求中都存在。这个假设在当通过 <code class=\"docutils literal notranslate\"><span class=\"pre\">htpasswd</span></code> 或者相似的认证机制来做Basic HTTP的认证时才是可行的，但是使用Negotiate (GSSAPI/Kerberos) 或者其它资源密集型的认证方法时就说不过去了，前端HTTP server的认证通常用在仅仅一个或不太多的登录URLs，而且在认证成功后，应用还要自己去维护这个session。</p>\n<p><a class=\"reference internal\" href=\"/zh-hans/6.1/ref/middleware/#django.contrib.auth.middleware.PersistentRemoteUserMiddleware\" title=\"django.contrib.auth.middleware.PersistentRemoteUserMiddleware\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">PersistentRemoteUserMiddleware</span></code></a> 就针对这个使用场景提供了支持。除非用户显式地退出登录，它将一直保留已认证的会话。这个中间件可以代替上文中的 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/middleware/#django.contrib.auth.middleware.RemoteUserMiddleware\" title=\"django.contrib.auth.middleware.RemoteUserMiddleware\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RemoteUserMiddleware</span></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.1/howto/"}],"prev":{"docname":"howto/static-files/deployment","title":"如何部署静态文件","url":"/zh-hans/6.1/howto/static-files/deployment/"},"next":{"docname":"howto/csp","title":"如何使用 Django 的内容安全策略","url":"/zh-hans/6.1/howto/csp/"},"formats":{"html":"/zh-hans/6.1/howto/auth-remote-user/","markdown":"/zh-hans/6.1/howto/auth-remote-user.md","json":"/zh-hans/6.1/howto/auth-remote-user.json"},"source":"https://github.com/django/django/blob/stable/6.1.x/docs/howto/auth-remote-user.txt","official":"https://docs.djangoproject.com/zh-hans/6.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","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}