2010-09-12 144 views
0

我有一个PHP脚本,测试用户是否登录,他访问的每个页面都在某个子目录中。如果他已经登录,他会得到该页面,否则他会被重定向到登录页面。相反,包括到每一个文件(不可能的,因为有些是二进制)这一点,我设置的.htaccess这样PHP身份验证+ mod_rewrite

RewriteEngine On 

RewriteCond %{REQUEST_FILENAME} !^$ 
RewriteRule (.*) /check.php?filename=special/$1 

而且check.php的内容

if (!isset($_SESSION['username'])) 
{ 
    header("location: /login.html"); 
    die(); 
} 
$filename = $_GET['filename']; 
include($filename); 

的问题是,检查.php易受本地文件包含,因为我可以通过../在文件名中移动到父目录,甚至离开/ var/www。我如何限制它只能从特殊目录中读取,或者如果PHP检查通过允许Apache读取目标文件而不是读取文件的PHP脚本,我可以通过什么方式取消重写?

编辑我也有特殊目录中的子目录。 check.php位于特殊目录的父目录中。

+0

这不适用于二进制。需要正确的头文件 – 2010-09-12 11:58:35

+0

是的,它是check.php的简化模型。我也可以找到文件的MIME类型并在头文件中发送Content-Type。 – Dmi 2010-09-12 12:12:44

回答

0

这工作:

$filename = realpath($_GET['filename']); 
if (strpos($filename, '/full/path/to/special') !== 0) 
{ 
die(); 
} 

如果到文件名的真正路径不以该字符串开始,它将中止。

0
$filename = basename($_GET['filename']); 

将只留下文件名关闭任何给定的字符串

+0

对不起,我忘了补充一点,我在目录中也有子目录,所以我不能删除整个路径。 – Dmi 2010-09-12 12:14:32

0

首先,从你的mod_rewrite规则删除“/特殊”的一部分,没有必要为它,你只想要一个文件名。

那就试试这个:

$your_dir = '/full/path/to/special'; 
$filename = basename($_GET['filename']); 
if (file_exists($your_dir . '/' . $filename)) { 
    include($filename); 
} 

基名()将切断从$文件名的路径。

0

为dir树设置自动前缀不是简单吗?

+0

如果我预先添加“subdir /”并且有人输入“../file”,他们会得到“/ file”而不是“subdir/file”。函数realpath解决了所有这些问题,以准确显示它将要使用的路径,并且如果它不以“subdir /”开头,我知道它不在目录中。 – Dmi 2010-09-15 22:57:34