AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 1085027
Accepted
Bob
Bob
Asked: 2021-12-01 16:56:20 +0800 CST2021-12-01 16:56:20 +0800 CST 2021-12-01 16:56:20 +0800 CST

Apache:将服务图像限制为经过身份验证的用户

  • 772

我正在尝试找出一种方法来限制对我的 apache 配置中的媒体文件夹的访问。该文件夹从 Django 站点进行上传,并且图像/pdf 上传显示在站点中以向经过身份验证的用户显示。问题是,任何未经身份验证的 schmo 都可以导航到mysite.com/media/images/pic1.jpg. 这应该是不可能的;我已经尝试了一些方法来限制这种行为,但我认为我需要一两个指针。

第一次尝试:XSendfile

Xsendfile 似乎工作,但它(顾名思义)发送文件以供下载,然后我应该显示图像的页面没有加载。所以看来这不是我的用例所需要的。

第二次尝试:重写规则

我在 apache 配置中添加了一些重写规则:

RewriteCond "%{HTTP_REFERER}" "!^$"
RewriteCond "%{HTTP_REFERER}" "!mysite.com/priv/" [NC]
RewriteRule "\.(gif|jpg|png|pdf)$"    "-"   [F,NC]

需要身份验证的站点的所有部分都在/priv/路径后面,所以我的想法是,如果这可行,那么导航到/media/images/pic1.jpg将被重写。但这不起作用,mysite.com/media/images/pic1.jpg仍然显示图像。

第三次尝试:环境

我在虚拟主机内的环境中尝试了类似的东西:

<VirtualHost *:80>
    ...
    SetEnvIf Referer "mysite\.com\/priv" localreferer
    SetEnvIf Referer ^$ localreferer
    <FilesMatch "\.(jpg|png|gif|pdf)$">
        Require env localreferer
    </FilesMatch>
    ...
</VirtualHost>

但这也没有用;我仍然可以直接导航到图像。

第四次尝试:需要有效用户

我添加Require valid-user到 v-host,但我不知道如何根据 Django 用户模型检查它。在此更改之后,每次加载显示图像的页面时,我都会收到登录提示(但没有 htaccess 等,没有什么可验证的,并且网站上也没有显示图像。

然后我尝试实现此处描述的内容(https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/apache-auth/),但我的 django 项目不喜欢WSGIHandler(与默认值相反get_wsgi_application())。我得到一个raise AppRegistryNotReady("Apps aren't loaded yet.")错误。看起来这可能是最合理的方法,但我不知道如何开始WSGIHandler工作,或者使用get_wsgi_application().

我知道我可以给文件一个难以猜测的类似 uuid 的名称,但这似乎是一个半途而废的解决方案。那么,限制对媒体文件夹的访问以使这些图像仅在用户通过身份验证的站点部分内链接的最佳策略是什么?

Ubuntu 20.04、阿帕奇 2.4

| 编辑,遵循一些建议 |

授权文件

def check_password(environ, username, password):
    print("---->>>---->>>---->>>---->>>---->>> check_password() has been called  <<<----<<<----<<<----<<<----<<<----")

    return True

#from django.contrib.auth.handlers.modwsgi import check_password

Apache 日志显示该脚本已加载,但该函数显然未执行,因为打印语句未出现在日志中。我在这个文件和 wsgi.py 文件中放置了一个杂散的打印语句,以确保该策略进入日志,只有 wsgi.py 文件中的策略进入日志。

虚拟主机:

<VirtualHost *:80>
    ServerName mysite.com
    ServerAlias mysite.com
    DocumentRoot /path/to/docroot/
    
    Alias /static/ /path/to/docroot/static/

    # Not sure if I need this
    Alias /media/ /path/to/docroot/media/

    <Directory /path/to/docroot/static/>
        Require all granted
    </Directory>

    <Directory /path/to/docroot/media/>
        Require all granted
    </Directory>

    # this is my restricted access directory
    <Directory /path/to/docroot/media/priv/>
        AuthType Basic
        AuthName "Top Secret"
        AuthBasicProvider wsgi
        WSGIAuthUserScript /path/to/docroot/mysite/auth.py
        Require valid-user
    </Directory>

    <Directory /path/to/docroot/mysite/>
        <Files "wsgi.py">
            Require all granted
        </Files>
    </Directory>

    WSGIDaemonProcess open-ancestry-web python-home=/path/to/ENV/ python-path=/path/to/docroot/ processes=10 threads=10
    WSGIProcessGroup mysite-pgroup
    WSGIScriptAlias / /path/to/docroot/mysite/wsgi.py

    LogLevel trace8
    ErrorLog "|/bin/rotatelogs -l /path/to/logs/%Y%m%d-%H%M%S_443errors.log 30"
    CustomLog "|/bin/rotatelogs -l /path/to/logs/%Y%m%d-%H%M%S_443access.log 30" combined
</VirtualHost>

|另一个编辑 |

我接受了答案,因为现在一切正常。有很多活动部件,这导致了答案的最初问题。(1) 测试 check_password 函数没有出现在 apache 日志中......好吧,它出现在/var/log/apache2/error.log而不是设置的自定义日志中。不知道为什么,但是好吧...

(2) 我的 venv 没有正确激活,我实际上并没有注意到这一点,因为 django 也安装在系统 Python 上。我从 virtualenv 复制activate_this.py脚本并将其添加到我的 venv 并将这样的东西添加到我的 wsgi 文件中

activate_this = '/path/to/ENV/bin/activate_this.py'
with open(activate_this) as f:
    exec(f.read(), {'__file__': activate_this})

修复这些问题后,从 wsgi.py 文件调用 check_password 函数即可工作。这里的“有效”意味着它限制对未经身份验证的用户不应访问的文件夹的访问。用户仍然需要提供两次凭据——一次在常规 django 视图中,一次在浏览器提示中。这很烦人,但实际上我的问题是关于限制访问的,所以我将它留到另一天。

从 auth.py 调用 check_password 的答案建议与我的项目不合作。我收到的错误提示它是在 wsgi.py 之前调用的——似乎在调用 check_password 时未加载 venv 或未加载设置。

django apache-2.4
  • 1 1 个回答
  • 381 Views

1 个回答

  • Voted
  1. Best Answer
    Razenstein
    2021-12-03T14:00:18+08:002021-12-03T14:00:18+08:00

    这就是 get_wsgi_application 正在做的事情:

    def get_wsgi_application():
        django.setup(set_prefix=False)     # this will lead to "apps_ready=true"
        return WSGIHandler()
    

    它在返回处理程序之前设置 django 环境。

    以下应该在您的 wsgi.py 中解决问题:

    application = get_wsgi_application()
    from django.contrib.auth.handlers.modwsgi import check_password
    # the sequence is important!!
    

    实际上问题出在 modwsgi.py 的第一行:

    UserModel = auth.get_user_model()
    

    因为 get_user_model() 将检查 apps_ready 以及所有在 python 执行文件导入的那一刻完成的事情!

    更好的方法是创建一个单独的 auth.py 并首先检查它是否真的被 Apache 调用,并通过简单的打印将转到 Apache 的 error.log:

    def check_password(environ, username, password):
        print("***********   check_password() has been called  ********")
        return True
    

    一旦运行,您可以用 import 语句替换它并使用 djangos check_password()。

    from django.contrib.auth.handlers.modwsgi import check_password
    

    然后在 httpd-vhosts.conf 中类似以下内容:

    <VirtualHost *:80>
    
       ....
    
       <Directory path_to_server_root/secret>
            AuthType Basic
            AuthName "Top Secret"
            AuthBasicProvider wsgi
            WSGIAuthUserScript path_to_wsgi/wsgi.py
            Require valid-user
       </Directory>
    
    </VirtualHost>
    
    • 1

相关问题

  • Apache Django Mod_Wsgi - 自动重新加载应用程序

  • 哪个 Apache 包最适合 mod_wsgi Django 应用程序?

  • 设置 Django 服务器以服务多个站点的最佳方式是什么?

  • 哪个最适合 Django?Lighttpd 还是 Nginx?或者也许是别的什么?[关闭]

  • 如何向运行共享 IIS 服务器的 Python 新手解释 Django/Python 安装 [关闭]

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve