在 Nginx 后面的 Gunicorn 中为 Trac 设置 REMOTE_USER

在 Nginx 后面的 Gunicorn 中为 Trac 设置 REMOTE_USER

我想在 Gunicorn 中运行 Trac,位于 Nginx 后面。Nginx 通过 LDAP 处理用户身份验证(可行),但我无法将其REMOTE_USER传递给 Trac。

对于 uWSGI 我会像这样配置 Nginx(已经测试并且有效):

uwsgi_param REMOTE_USER $remote_user;

对于 Gunicorn,我找不到类似的配置指令。我尝试设置标头,但似乎没有改变任何东西:

proxy_set_header REMOTE_USER $remote_user;

Trac wiki 中关于此内容的条目,注意到“wsgi 入口点不处理 [...] 身份验证”,以及使用本地密码文件处理基本身份验证的解决方法,这不是我所需要的。我是否需要更改入口点以将此REMOTE_USER标头传递给正确的环境变量?目前只是这样:

import sys
import os

sys.stdout = sys.stderr

os.environ['TRAC_ENV'] = '/path/to/my/trac'

import trac.web.main
application = trac.web.main.dispatch_request

答案1

很奇怪。我通过像你提到的那样在 nginx 配置中包含这个来让它工作

proxy_set_header REMOTE_USER $remote_user;

然后对于 trac.wsgi 文件

import trac.web.main
def application(environ, start_application):
    environ['REMOTE_USER'] = environ.get('HTTP_REMOTE_USER')
    return trac.web.main.dispatch_request(environ, start_application)

取代这个

import trac.web.main
application = trac.web.main.dispatch_request

在你的 trac.wsgi 中

显然,正在进行的“HTTP_”中存在一些问题,导致 trac 的身份验证混乱

我猜想,通过对“HTTP_AUTHORIZATION”请求标头执行相同的操作,可能也能实现相同的效果,但我没有尝试这样做。所以我不确定,我只知道它现在有效!

答案2

我在使用 Mercurial 时遇到了类似的问题;上述 byoungb 的回答在原则上是可以的,但应该使用X-Remote-User,而不是REMOTE_USER在 中使用proxy_set_header,然后在 调用HTTP_X_REMOTE_USER中使用environ.get()

但是,由于大多数人使用 SSL,然后进行基本身份验证,因此您可以使用标Authorization头(以 的形式到达您的环境HTTP_AUTHORIZATION),如下所示:

import base64, re

def use_basic_auth(application):
    def auth_app(environ, start_response):
        auth = environ.get('HTTP_AUTHORIZATION')
        if auth:
            scheme, creds = re.split(r'\s+', auth)
            if scheme.lower() != 'basic':
                raise ValueError('Unknown auth scheme \"%s\"' % scheme)
            user, pword = base64.b64decode(creds).split(':', 1)
            environ['REMOTE_USER'] = user

        return application(environ, start_response)
    return auth_app

然后你可以写(对于 Trac)

application = use_basic_auth(trac.web.main.dispatch_request)

或者,就我的情况而言(对于 Mercurial)

application = use_basic_auth(hgweb(config))

如果您使用的是 HTTP Basic 身份验证以外的其他方法,这显然不起作用。在这种情况下,您可以按照 byoungb 的建议(尽管使用更好的标头名称),也可以将身份验证移至 Python 端,而不是让 nginx 执行此操作。后者的缺点是,您可能如果某个地方存在安全漏洞,就会更容易受到攻击。

相关内容