如何重定向Apache“Index of ...”页面?

时间:2012-06-11 12:59:00

标签: php apache redirect

我正在尝试使用PHP通过Apache的autoindex module在Apache中实现经过身份验证的文件列表。

我想象的方式是让Apache将PHP脚本作为header file运行。我已经设法让Apache为头文件正确运行PHP,它也检测到登录cookie。但似乎Apache将头文件作为单独的请求运行,这意味着如果我尝试从PHP发送重定向头,则它不会运行。

我的(简化)Apache配置:

DocumentRoot "/path/to/files_root"
Alias /~extra "/path/to/extra-data"

<Directory "/path/to/extra-data">
    Options -Indexes -MultiViews +Includes
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>

IndexOptions FancyIndexing HTMLTable SuppressHTMLPreamble
AddType text/html .php .html .htm
AddOutputFilter INCLUDES .php
AddHandler application/x-httpd-php .php
HeaderName "/~extra/HEADER.php"

我的HEADER.php文件:

<?php

if ( ! my_validate_cookie_function()) {
    header('HTTP/1.1 302 Found');
    header('Location: http://login.example.com/');
    exit(1);
}

因此,标题不会发送到浏览器。设置Apache环境viariables似乎不起作用,因为它们在HEADER.php完成执行时就已经很久了。

Cookie本身已加密,因此需要PHP验证它。

有任何建议如何达到预期的效果?

4 个答案:

答案 0 :(得分:3)

您应该使用index.php标记中的以下代码将<body>文件插入您的目录。

function fileindex($folder) {
    if (!is_dir($folder)) {
        return array(); //empty if not a folder
    }
    $list = scandir($folder);
    array_shift($list); //first two values are always . & ..
    array_shift($list);
    return $list;
}
/* auth stuff here */
if (is_auth) {
    echo "<h1> Index of ".getcwd()."</h1>\n<ul>";
    echo "\n<li><a href=\"/\">Parent Directory</a>";
    foreach (fileindex(".") as $i) {
        echo "\n<li><a href=\"".$i."\">".htmlentities($i, ENT_QUOTES|"ENT_HTML401", "UTF-8", true)."</a></li>";
    }
    echo "</ul>";
}

既然你告诉我你不能使用index.php,你应该使用Apache将目录重定向到wherever/other.php?directory=path并从那里开始工作。

.htaccess中,解决方案将是

RewriteCond %{REQUEST_URI} -d
RewriteRule ^(.*)$ wherever/other.php?directory=$1 [L]

然而,最值得注意的是,您需要稍微编辑PHP代码以适应作为$_GET参数的文件夹,而不是getcwd()fileindex(".")

答案 1 :(得分:0)

exit(1)中的1可能是问题所在。尝试删除该号码。

我知道exitdie的别名,die会将每个文本打印到客户端。

顺便说一句,我建议使用mod_rewrite。如果cookie存在,您可以与RewriteCond核实。如果您想查看更多内容,例如会话变量这不起作用。

答案 2 :(得分:0)

您可以使用此代码:

<Directory "/path/to/files_root">
  DirectoryIndex redirected_page.php
</Directory>

答案 3 :(得分:0)

这是我最终的结果。荣誉前往Scott S,他向我暗示了解决方案。

Apache配置:

ServerName listing.example.com
# A path to a location which you wanted listed
DocumentRoot "/path/to/listed/location"

<Directory "/path/to/listed/location">
    # Ignore .htaccess files
    AllowOverride None
    # Disable Apache's own indexing, CGI execution and Apache Includes
    Options -Indexes -MultiViews -ExecCGI -Includes FollowSymLinks
    Order allow,deny
    Allow from all
</Directory>

<Directory "/path/to/php/listing/app">
    Options -MultiViews ExecCGI
    Order allow,deny
    Allow from all
</Directory>

<IfModule dir_module>
    # index.php should not be listed here as we will not want PHP scripts to be executed
    DirectoryIndex index.html index.htm
</IfModule>

<IfModule alias_module>
    # This is for CSS/JS files
    Alias /~media /path/to/php/listing/app/media
</IfModule>

<IfModule xsendfile_module>
    # Because the files listed might be large, we want to pass the file handling
    # to Apache via XSendFile Module
    # @see: https://tn123.org/mod_xsendfile/
    XSendFile on
    XSendFilePath "/path/to/listed/location"
</IfModule>

# Uncomment the two setting below if your listing a mounted drive
# EnableSendfile Off
# EnableMMAP Off

<IfModule rewrite_module>
    RewriteEngine On
    # Make sure there are trailing slashes for Directory URLs
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
    RewriteRule ^(.*[^/])$ $1/ [R=302,L]
    # Pass all file+dir requests to a PHP handler
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d [OR]
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f
    RewriteRule .* /path/to/php/listing/app/index.php/$0 [L]
</IfModule>

和我的PHP脚本(非常简化的版本):

<?php

if (my_authentication_check()) {
    $requested_path = realpath($_SERVER['DOCUMENT_ROOT'] . $_SERVER['REQUEST_URI']);
    $filename = substr($requested_path, strrpos($requested_path, DIRECTORY_SEPARATOR) + 1);

    if ($requested_path) {
        if (is_dir($requested_path)) {
            // Show dir contents
            $dir_contents = scandir($requested_path);
        } else {
            // Pass file download to XSendFile module
            header('X-Sendfile: ' . $requested_path);
            header('Content-Type: ' . my_get_file_mime($filename));
            exit;
        }
    } else {
        // display 404 error
    }
} else {
    // redirect to login screen, or display an error... whatever you fancy
}

我实际上使用Kohana框架和我自己的库来处理身份验证检查,显示列表等。您还必须考虑文件权限。例如。在* nix系统上,您需要检查dirs是否具有可执行权限,而在Windows上读取访问就足够了。