我将所有图像保存在普通用户无法访问的根目录中。我随机生成所有文件名,所以我不希望他们知道文件的路径或名称。目前,我有img
元素:
<img src="get_image.php?id=1">
我的get_image.php
页面如下:
<?php
include_once 'includes/db_connect.php';
include_once 'includes/functions.php';
$uploaddir = '/root/......./uploads/'; //Direct path from root to folder holding files
$id = $_GET['id'];
if(!is_numeric($id)) {
die("File id must be numeric");
}
// A QUICK QUERY ON A FAKE USER TABLE
$stmt = $mysqli->prepare("SELECT `name`, `mime` FROM `uploads` WHERE `filmId`=?");
$stmt->bind_param("i", $id);
$stmt->execute();
$stmt->bind_result($name, $mime);
// GOING THROUGH THE DATA
while($stmt->fetch()) {
header("Content-Type: " . $mime);
readfile($uploaddir.$name);
}
?>
如果有的话,我可以这样做吗?我不想直接调用图像文件src:
<img src="../../../uploads/file.jpg"> <!-- I don't want to do this -->
这样做会给用户(或攻击者)一个关于我保存上传文件的位置的提示。这些图像是用户上传的,因此如果攻击者上传带有恶意代码的图像(即使我有大量代码检查和验证文件),他们也不会知道该文件的保存位置。
此外,我是网络开发的新手并保证其安全。如果您有任何提示或指针添加到我必须使我的网页更安全,请随意。谢谢!
我正在使用this link来确保此功能的安全。
解决方案:
而不是:
header("Content-Type: " . $mime);
readfile($uploaddir.$name);
我说这个:
header("Content-Type: " . $mime);
$contents = file_get_contents($uploaddir . $name);
echo $contents;
它有效。
答案 0 :(得分:1)
不仅如此,你可以做到这一点。您甚至可以将<img>
指向一个似乎是图像路径的PHP脚本。例如:
<img src="phpimages/my_image.png" />
这个技巧需要一个Apache HTTP服务器(你无疑会使用它)和mod_rewrite
插件(你确定已安装)。
您可以将.htaccess
文件放在/phpimages/
中,其中包含以下内容:
RewriteRule ^([^\.]+)\.(png|jpg|gif)$ /image.php?file=$1.png [NC,L]
如果您只想要用户ID,可以将正则表达式限制为:
RewriteRule ^([0-9]+)\.(png|jpg|gif)$ /image.php?file=$1.png [NC,L]
进一步解释了此过程here。
在脚本image.php
(在同一目录中)中,然后将文件名作为字符串,例如:
$filename = $_GET["file"]; //eg.: "file1.jpg"
不要忘记过滤../
次黑客攻击。要将文件打印给用户,只要它确实存在,请使用readfile
:
const REAL_AVATAR_PATH = "../../../uploads/"
if(file_exists(REAL_AVATAR_PATH.$username)) {
header("Content-Type: image/jpg"); //For simplicity, I have ommited to send different header for different images as "png", "gif" and so on.
readfile(REAL_AVATAR_PATH.$username);
}
else {
header("HTTP/1.0 404 Not Found");
die("Error 404 - sorry");
}
在您的情况下,您可以将路径设为/avatars/[number].png
(并将所有图片转换为png
)。
答案 1 :(得分:1)
而不是:
header("Content-Type: " . $mime);
readfile($uploaddir.$name);
我说这个:
header("Content-Type: " . $mime);
$contents = file_get_contents($uploaddir . $name);
echo $contents;
它有效。
答案 2 :(得分:0)
我不同意目前的答案。如果您正在查看数据库,那么您可以轻松地执行以下操作:
<img src="/phpimages.php?id=23" alt="{ALT}" />
然后 phpimages.php
将获取ID 23并输出该文件。你的最终用户不知道图像来自哪里;他们甚至可以来自另一台服务器。此选项还允许更易读的代码,同时仍保持相同的安全性。
<img src="/phpimages.php?frontImage" alt="{ALT}" />
现在,您只需使用下面链接中描述的内容,即可获得第一个$ _GET关联的密钥。或者您可以将其设为id=frontImage
,然后使用$_GET['id']
答案 3 :(得分:-1)
在PHP文件中,您需要将标题内容类型设置为
header('Content-Type: image/png');
以便浏览器知道get_image.php将图像作为响应
让临时图像的路径存储在$ path
中<?php
$im = imagecreatefrompng($path);
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
?>