Я хочу запустить Trac в Gunicorn за 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
Странный. Я получил это, включив это в конфигурацию 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, но я не пытался этого. Так что точно не знаю, знаю только то, что теперь это работает!
У меня была аналогичная проблема с 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. В этом случае вы можете либо сделать то, что предлагает byoungb (хотя и использовать более удачное имя заголовка), либо перенести аутентификацию на конец Python, а не заставлять nginx делать это. Обратной стороной последнего является то, что вы мощь быть более уязвимым, если где-то есть дыра в безопасности.