代码之家  ›  专栏  ›  技术社区  ›  Bart

使用PHP/Apache限制对静态文件(html、css、img等)的访问

  •  38
  • Bart  · 技术社区  · 16 年前

    假设您在服务器的一个目录中有许多html、css、js、img等文件。通常,internet land中的任何用户都可以通过键入完整URL访问这些文件,如下所示: http://example.com/static-files/sub/index.html

    现在,如果您只希望授权用户能够加载这些文件,该怎么办?对于本例,假设您的用户首先从如下URL登录: http://example.com/login.php

    到目前为止,我提出了两种可能的解决方案:


    在“静态文件”下创建以下.htaccess文件:

    Options +FollowSymLinks  
    RewriteEngine on  
    RewriteRule ^(.*)$ ../authorize.php?file=$1 [NC]
    

    然后在authorize.php中。。。

    if (isLoggedInUser()) readfile('static-files/'.$_REQUEST['file']);
    else echo 'denied';
    

    这个authorize.php文件过于简化了,但是您明白了。


    在“静态文件”下创建以下.htaccess文件:

    Order Deny,Allow
    Deny from all
    Allow from 000.000.000.000
    

    然后我的登录页面可以为每个登录的用户附加一个IP。显然,这还需要某种清理例程来清除旧的或不再使用的IP。


    我担心我的第一个解决方案在服务器上会变得非常昂贵,因为他们正在访问的用户和文件数量会增加。我认为我的第二个解决方案会便宜得多,但由于IP欺骗等原因,安全性也会降低。我还担心,如果同时有许多用户,将这些IP地址写入htaccess文件可能会成为应用程序的瓶颈。

    以下哪种解决方案听起来更好,为什么?或者,你能想出一个完全不同的解决方案,比这两个都好吗?

    9 回复  |  直到 16 年前
        1
  •  37
  •   Shane    16 年前

    <img src='picture.jpg' /> <img src='load_image.php?image=picture.jpg' /> .

    图像加载器可以验证会话、检查凭据等,然后决定是否将请求的文件返回到浏览器。这将允许您将所有安全文件存储在可通过web访问的根目录之外,这样就不会有人只是“意外地”将它们下载或浏览到那里。

    只需记住在PHP中返回正确的标题,并在PHP中执行readfile()之类的操作,即可将文件内容返回到浏览器。

    我已经在几家大型安全网站上使用过这种设置,它的效果非常好。

    编辑:我目前正在构建的系统使用这种方法加载Javascript、图像和视频,但我们并不十分担心CSS的安全性。

        2
  •  9
  •   NullUserException Mark Roddy    9 年前

    X-Sendfile

    Apache(和其他HTTP服务器)有一个模块,可以让您告诉HTTP服务器为您在php代码的头中指定的文件提供服务: 因此,您的php脚本应该如下所示:

    // 1) Check access rights code
    // 2) If OK, tell Apache to serve the file
    header("X-Sendfile: $filename");
    

    2.可能出现的问题:

    1. 您需要有权重写规则(.htaccess已启用或直接访问配置文件)
    2. 您需要将modxsendfile模块添加到已安装的Apache中

    https://stackoverflow.com/a/3731639/2088061

        3
  •  5
  •   Community Mohan Dere    9 年前

    here

    但我只是有一个 非常 有趣的想法是 可以

    • /sessions 在web服务器上的某个位置。

    • 每当用户登录时,在中创建一个会话ID为的空文本文件 . 例如。 123456

    • 在PHP应用程序中,提供如下图像: /sessions/123456/images/test.jpg

    • 在htaccess文件中,有两个重定向命令。

    • 翻译者 进入 /sessions/123456?filename=images/test.jpg

    • 第二个可以捕捉到任何呼叫的 //sessions/(.*) 并使用 -f /sessions/123456 不存在,表示用户已注销或会话已过期。在这种情况下,Apache会发送403或重定向到错误页面-资源不再可用。

    这样,我们就可以在mod_rewrite中进行准会话身份验证,只需进行一次“文件存在”检查!

    我没有足够的例程来动态构建mod_rewrite语句,但它们应该很容易编写(我满怀希望地朝你的方向看(秋葵:)

    注意事项和注意事项:

    • 过期的会话文件必须使用cron作业快速删除,除非可以在.htaccess中检查文件的mtime(这很有可能)。

    • 图像/资源可用 给任何客户 只要会话存在,就没有100%的保护。您可以通过将客户端IP添加到等式(=您创建的文件名)中并对%{REMOTE_ADDR}进行额外检查来解决此问题。这是先进的。htaccess精通,但我确信它是可行的。

    我是 对这方面的反馈感兴趣,我可能忽略的任何不足或不可能,以及任何成功的实现(我现在没有时间自己设置测试)。

        4
  •  3
  •   Ignacio Vazquez-Abrams    16 年前

    创建一个 rewrite map

        5
  •  2
  •   symcbean    16 年前

    维护htaccess文件的内容看起来是一场噩梦。此外,您声明的目标是防止未经身份验证 使用者 无法访问此内容-因此该方法不适用于以下目的:

    多个用户可能来自同一IP地址

    单个用户会话可能来自多个地址。

    我担心我的第一个解决方案在服务器上会变得非常昂贵,因为 他们正在访问的用户和文件增加

    如果您想防止内容流失,并且不想使用HTTP AuthenitAction,那么将所有文件访问包装在附加的逻辑层中是唯一明智的选择。另外,您不知道使用PHP来实现这一点 是 一个问题-你测试过吗?我想你会惊讶于它能提供多大的吞吐量,特别是如果你使用操作码缓存的话。

    C

        6
  •  0
  •   GG.    16 年前

    我编写了一个动态web应用程序并将其部署在WebSphere应用程序服务器上,下面是我保护静态文件的方法:

    <login-config id="LoginConfig_1">
      <auth-method>FORM</auth-method>
        <realm-name>Form-Based Authentication</realm-name>
          <form-login-config>
            <form-login-page>/login.html</form-login-page>
            <form-error-page>/login_error.html</form-error-page>
           </form-login-config>
    </login-config>
    

    在web.xml中,它将告诉您的web服务器使用基于表单的身份验证(下面给出了使用登录名的代码)。

    <form id="form1" name="form1" method="post" action="j_security_check" style="padding: 0px 0px 0px 12px;">
            Username: 
              <label>
              <input name="j_username" type="text" class="font2" />
            </label>
    
            <br />
            <br />
            Password:
            <span class="font2" >
            <label>
          <input name="j_password" type="password" class="font2" />
          </label>
          </span> 
            <br />
            <br />
                <label>
            <input type="submit"  class="isc-login-button" name="Login" value="Login" />
            </label>
        </form></td>
    

    您可以声明您的安全资源,并且每当用户尝试访问这些资源时,容器都会自动检查用户是否经过身份验证。甚至您也可以使用安全资源附加角色。为此,我在web.xml中添加了以下代码

    <security-constraint>
            <display-name>Authenticated</display-name>
            <web-resource-collection>
                <web-resource-name>/*</web-resource-name>
                <url-pattern>/*</url-pattern>
                <http-method>GET</http-method>
                <http-method>PUT</http-method>
                <http-method>HEAD</http-method>
                <http-method>TRACE</http-method>
                <http-method>POST</http-method>
                <http-method>DELETE</http-method>
                <http-method>OPTIONS</http-method>
            </web-resource-collection>
            <auth-constraint>
                <description>Auth Roles</description>
                <role-name>role1</role-name>            
                <role-name>role2</role-name>            
            </auth-constraint>
        </security-constraint>
    
        <security-role>
            <role-name>role1</role-name>
        </security-role>
        <security-role>
            <role-name>role2</role-name>
        </security-role>
    

    因此,在用户以角色role1和role2登录之前,此代码不会让用户看到任何静态文件(因为/*)。因此,通过这种方式,您可以保护您的资源。

        7
  •  0
  •   askmish    14 年前

    如果您使用的是apache,则可以在.htaccess或httpd.conf文件中进行如下配置。下面是阻止访问*.inc文件的示例。这对我很有用。

    <Files ~ "\.inc$">
    Order allow,deny
    Deny from all
    </Files>
    

    http://www.ducea.com/2006/07/21/apache-tips-tricks-deny-access-to-certain-file-types/ .

        8
  •  0
  •   Andreas Dyballa    11 年前

    你所有的静态文件 你必须从服务器上发送它们 在webroot中 ,可以保护除HEAD之外的所有HTTP方法。 如果您获得授权,您可以发出一个head请求,通过header发送filecontent作为body。 当然,这是昂贵的,但你是受保护的,你有同样的行为。

        9
  •  0
  •   RafaSashi    9 年前

    我可能会有一个基于 iframe HTTP_REFERER 但它不是防弹的,这将取决于您希望通过这种访问保护什么。

    1-使用PHP页面对用户进行身份验证

    <iframe src="static/content.html" />
    

    3-然后在htaccess中,您可以检查HTTP_REFERER中的密钥,如下所示:

    RewriteEngine On
    RewriteCond %{HTTP_REFERER} !AUTH_KEY
    RewriteCond %{REQUEST_URI} ^/path/to/protected/page$
    RewriteRule . - [F]
    

    4-最后,如果你想让它更具动态性,而不是每次都使用相同的键,你可以使用 rewrite map 根据Ignacio Vazquez Abrams的回答,或者使用用户IP作为文件名创建一个文件,并使用 REMOTE_ADDR 然后在一段时间后删除该文件。

    但请记住,iframe+HTTP\u REFERER的行为可能会因浏览器会话和远程地址的不同而有所不同,因此它的有限性。。。

    推荐文章