可选择将REMOTE_USER传递给应用程序

时间:2015-12-08 23:48:34

标签: apache apache2 basic-authentication form-authentication

在我们公司,我们有一个运行django应用程序(通过wsgi)和一些遗留php应用程序的apache服务器。为了获得某种单点登录,我们决定使用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)的欢迎。

如果未经身份验证的用户进入/ mix-zone,则不应提示他或她输入凭据。

我们到目前为止尝试的是省略/ mixed-zone中的ReqireAll标记,这导致apache永远不会设置REMOTE_USER,即使用户之前已登录。

1 个答案:

答案 0 :(得分: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