При желании передать 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
Другие вопросы по тегам