我正试图通过使用在上传过程中创建并分配给文件的文件令牌,将文件从SQL推送到浏览器。但是我的SELECT SQL不适用于除文件id字段之外的任何其他字段,该字段似乎是唯一一个触发SELECT请求的字段,这里是代码
$item = $_GET['item'];
$sql = 'SELECT * FROM `files` WHERE file_token = '.$item.'';
$result = mysql_query($sql);
if(!$result) {
echo '<div style="padding:8px;background-color:#fae3e3;border:2px solid #b25959;color:#313131;">Error!</div>';
} else {
while($obj = mysql_fetch_array($result)) {
$file_type = $obj['file_type'];
$file_size = $obj['file_size'];
$file_name = $obj['file_name'];
$file_hash = $obj['file_hash'];
$name = 'encrypted/'.$file_hash;
if (file_exists($name)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file_name));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($name));
ob_clean();
flush();
readfile($name);
exit;
}
}
}
mysql_query("UPDATE `files` SET file_views = file_views+1 WHERE file_token = '.$item.'");
mysql_close();
我的SELECT语句有问题吗?SQL 中的令牌如下所示
示例:3ed3:3ba6:eb24:5816:6d8b:be06:79e1:b20b
尝试:
$sql = 'SELECT * FROM `files` WHERE file_token = '''.$item.'''';
尝试在$item 上加引号
$sql='SELECT*FROM files
WHERE file_token="'.$item.'"';
$item = $_GET['item'];
$sql = 'SELECT * FROM `files` WHERE file_token = '.$item.'';
$item
设置为用户想提供给您的任何内容,然后直接放入您的查询中。如果用户礼貌地发送一个实际的文件令牌,那么一切都会很好:
// http://example.com/yourapp.php?item=5
SELECT * FROM `files` where file_token = 5;
如果用户发送一些随机的数据串,该怎么办?
// http://example.com/yourapp.php?item=John%20Doe
SELECT * FROM `files` where file_token = John Doe;
上述SQL将无效。该字符串需要有引号,例如:
SELECT * FROM `files` where file_token = "John Doe";
编辑代码以简单地添加引号似乎已经足够了,但事实并非如此。如果我们看看这样的解决方案:
$sql = 'SELECT * FROM files WHERE file_token = "'.$item.'"';
我们确实会在用户传入的内容周围添加引号。因此,在John Doe
的例子中,我们可以得到引用了John Doe
的正确SQL。如果用户决定提交一个带有术语5"; TRUNCATE TABLE files;
"的GET请求,该怎么办?
我们的SQL最终看起来像:
SELECT * FROM files WHERE file_token = "5"; TRUNCATE TABLE files; "";
单个查询现在变成3:
SELECT * FROM files WHERE file_token = "5";
TRUNCATE TABLE files;
"";
你可以尝试通过点画分号或类似的方式走得更远;但没有必要重新发明轮子。查看这个伟大的SO答案,了解在PHP中防止SQL注入的细节。