При желании передать REMOTE_USER в приложение
В нашей компании у нас есть сервер Apache, на котором запущено приложение django (через wsgi) и несколько устаревших php-приложений. Чтобы иметь какой-то единый знак, мы решили использовать mod_auth_form и wsgi в качестве AuthFormProvider. В самом django мы включили RemoteUserBackend и все работает отлично. Устаревшие приложения php также защищены через mod_auth_form и wsgi.
Проблема в том, что есть некоторые места, которые должны быть доступны для аутентифицированных и анонимных пользователей, где аутентифицированные пользователи имеют некоторые дополнительные функции (например, личное приветствие или активную кнопку выхода из системы).
Однако в нашей текущей конфигурации я не могу сказать, чтобы apache установил REMOTE_USER, если пользователь уже вошел в систему, но не запрашивает пароль, если пользователь не вошел в систему.
Я попытаюсь привести пример того, чего я хочу достичь.
Это пример конфигурации.
<Location "/protected-zone">
AuthType basic
AuthName "private area"
AuthBasicProvider file
AuthUserFile /usr/local/etc/apache2/userfile.htaccess
<RequireAll>
Require valid-user
</RequireAll>
</Location>
<Location "/mixed-zone">
AuthType basic
AuthName "private area"
AuthBasicProvider file
AuthUserFile /usr/local/etc/apache2/userfile.htaccess
<RequireAll>
Require [todo]
</RequireAll>
</Location>
Если пользователи переходят в /protected-zone, их нужно попросить ввести пароль - это довольно просто. Если пользователь затем переходит в /mixed-zone (после успешного входа в систему), его или ее следует приветствовать своим именем пользователя (на основе заголовка REMOTE_USER).
Если неаутентифицированный пользователь попадает в / смешанную зону, ему или ей не нужно вводить учетные данные.
До сих пор мы пытались опустить тег ReqireAll в / mixed-zone, что приведет к тому, что apache никогда не установит REMOTE_USER, даже если пользователь вошел в систему ранее.
1 ответ
Благодаря комментарию о сессиях я наконец смог решить проблему в нашем конкретном случае.
Теперь мы используем сеансы, как в примере ниже.
SessionMaxAge [age in seconds]
SessionCookieName session-cookie path=/;httponly;secure;version=1
SessionCryptoPassphrase [some random string]
<Location "/protected-zone">
Session On
SessionEnv On
AuthType basic
AuthName "private"
AuthBasicProvider file
AuthUserFile /usr/local/etc/apache2/userfile.htaccess
<RequireAll>
Require valid-user
</RequireAll>
</Location>
<Location "/mixed-zone">
Session On
SessionEnv On
</Location>
Если для параметра SessionEnv установлено значение On, apache устанавливает в заголовке дополнительный заголовок HTTP_SESSION, который может использоваться базовым приложением (см. Пример PHP ниже).
<?php
$session = array();
parse_str($_SERVER['HTTP_SESSION'], $session);
$username = $session['private-user'];
?>
Поскольку мы используем django, я написал небольшое промежуточное программное обеспечение, которое выполняется перед RemoteUserMiddleware и устанавливает REMOTE_USER в соответствии с пользователем в сеансе, если оно не было указано ранее.
from urllib.parse import parse_qs # works in pyhton3
class SessionUserMiddleware (object):
"""
Middleware to extract a user from a session if no REMOTE_USER is set.
"""
header = "REMOTE_USER"
session_header = "HTTP_SESSION"
session_key = "private-user"
def process_request(self, request):
if self.header not in request.META or not request.META[self.header]:
try:
username = parse_qs(request.META[self.session_header])[self.session_key]
request.META[self.header] = username
except KeyError:
pass