使用 PHP/Apache 根据数据库值控制对文件的访问


Control access to files based on DB values with PHP/Apache

我想要的

我正在制作一个系统,当用户上传图像时,它会转到文件夹images,其中有两个图像副本,一个拇指和一个更大的拇指。

现在,当用户上传图像时,它会与在MySQL数据库中插入一行一起完成,其中图像获得一个id,并且该行包含一个值,该值确定图像是否可供公众使用(1表示仅拇指可用,2表示两者)以及图像的所有者(管理员)。

我不想做的是,如果用户尝试通过转到图像的 URL 来访问图像,并且数据库中的值说它不应该公开可用,并且该用户的会话不是图像的所有者,(管理员未登录)它应该说找不到图像或访问被拒绝。

我想象的

如果可以用 php 完成,我会想象这样的事情:

//User tries to go to URL "images/IMAGE-ID_thumb.jpg"
if($img['access'] >= 1 || $_SESSION['admin_ID'] == $img['owner_ID']) {
  //Show image thumb
}
else {
  //Access denied
}

我也许可以将图像隐藏在受.htaccess保护的文件夹中,创建一个接受URL变量的imgae_get.php,查看图像是否可用,如果是,则加载图像。我只是想避免必须反编译/重新编译映像和其他服务器耗电进程。

我的问题是,我可以这样控制图像吗?有没有办法让 php 脚本显示为内部加载的图像?或者除了通过 PHP 之外,还有其他/更好的方法吗?(也许是阿帕奇?任何建议都非常感谢。

//get_image.php
//Do session/mysql checks as outlined in your code above.
header("Content-Disposition: filename=$imagename.$filetype");
header("Content-type: $mimetype");
readfile(PROTECTED_IMAGE_FOLDER . "$imagename.$filetype");

您可以使用DocumentRoot中的".htaccess"文件重定向对某些文件类型(或文件名,任何可以正则表达式)的所有请求:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule '.(gif|jpg|jpeg|png)$ imageHandler.php [NC,L]

您可以确定来自$_SERVER超全局的原始请求,并使用适当的标头来提醒浏览器您要返回图像。然后你从磁盘读取图像(使用file_get_contents()或类似),并使用echo将其写入浏览器,就像输出HTML一样。

.htaccess

#mod_rewrite
RewriteRule ^(.*)_(full|thumb).(jpg|png|gif)$ image.php?i=$1&type=$2&ext=$3

.HTML

<img src="http://example.com/image-1_thumb.png" />
=
<img src="image.php?i=image-1&type=thumb&ext=png" />

PHP(图片.php)

<?php 
// do basic sanity checks on input
$_GET['i'] = isset($_GET['i']) ? basename($_GET['i']) : null;
$_GET['type'] = isset($_GET['type']) ? basename($_GET['type']) : null;
//unsafe way
//$_GET['ext'] = isset($_GET['ext']) ?  basename($_GET['ext']) : null;
//safe way
$_GET['ext'] = in_array($_GET['ext'], array('png','gif', 'png')) ? $_GET['ext'] : null;
## Do DB Checks on session to owner ect 
/* $_GET
    [i] => image-1
    [type] => thumb
    [ext] => png
*/
// then output
if (file_exists('hiddenimagesfolder/images/'.$_GET['i'].'_'.$_GET['type'].'.'.$_GET['ext'])) {
    header("Content-Type:image/png");
    readfile('hiddenimagesfolder/images/'.$_GET['i'].'_'.$_GET['type'].'.'.$_GET['ext']);
} else {
    //not found
}
?>

"mod_rewrite" 所有尝试通过伪造的路径名访问图像到 PHP 文件,并将图像文件名作为查询参数,然后在那里施展魔法。将图像存储在公用文件夹之外应防止任何不需要的公共访问。或者,将实际图像存储在数据库本身中。