【PHP】防止文章附件被盗链,单文件解决方法

根据论坛两位大佬指定,研究 nginx 与 apache 规则限制放盗链;

经测试发现自己虚拟主机 .htaccess 设置 Deny from all 无效果,应该是被服务器全局设置覆盖了;

找到以下解决方法分享以一下:

图片[1]|【PHP】防止文章附件被盗链,单文件解决方法|不死鸟资源网

下面附上代码:

<?php
$refer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
$whitelist = ['ximi.me', 'www.ximi.me', 'dalao.net', 'www.dalao.net'];
$host = parse_url($refer, PHP_URL_HOST);
//echo $refer;
//echo $host;

if (!in_array($host, $whitelist)) {
  // die('NO'); //
   // 如果不在白名单中,‌执行退出操作

echo '<h2>访问被拒,‌拒绝盗版站点访问哦.</h2>';
echo '<h2><a href="https://www.ximi.me/666.html" target="_blank" >原文地址</a></h2>';
exit; // 测试地址: http://www.ximi.me/down.php?url=test.zip

}

?>

<?php

// 假设通过GET参数传递文件名和验证信息
$fileName = $_GET['url'];
$filePath = "./a/b/d/" . $fileName; //这里是文件存放位置

//echo $fileName;// . $filePath;

// 用户验证逻辑(‌示例省略,‌实际使用时应添加)‌

if (file_exists($filePath)) {

    // 设置HTTP头以准备文件下载
    header('Content-Type: application/zip');
    header('Content-Disposition: attachment; filename="' . basename($filePath) . '"');
//echo $refer . $filePath;
    header('Content-Length: ' . filesize($filePath));
    readfile($filePath);
    exit;
}
else {
die('文件不存在');
exit;

}

?>

似乎有了新的问题,这方法下载下来的文件会出现文件损坏,继续折腾。。。

感谢typecho群内 “极乐”大佬帮助,现已修复,新的完整代码:

<?php
// 设置错误报告
error_reporting(E_ALL);
ini_set('display_errors', 1);

// 引用检查
$refer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
$whitelist = ['ximi.me', 'www.ximi.me', 'dalao.net', 'www.dalao.net'];
$host = parse_url($refer, PHP_URL_HOST);

if (!in_array($host, $whitelist)) {
    header("HTTP/1.0 403 Forbidden");
    echo '<h2>访问被拒,拒绝盗版站点访问。</h2>';
    echo '<h2><a href="https://www.ximi.me/666.html" target="_blank">原文地址</a></h2>';
    exit;
}

// 文件下载处理
$fileName = isset($_GET['url']) ? $_GET['url'] : '';
if (empty($fileName)) {
    header("HTTP/1.0 400 Bad Request");
    die('未指定文件名');
}

// 安全地构建文件路径
$baseDir = realpath("./a/b/d");
$filePath = $baseDir . DIRECTORY_SEPARATOR . basename($fileName);

// 检查文件是否在允许的目录中
if (strpos(realpath($filePath), $baseDir) !== 0) {
    header("HTTP/1.0 403 Forbidden");
    die('访问被拒绝');
}

if (!file_exists($filePath) || !is_file($filePath)) {
    header("HTTP/1.0 404 Not Found");
    die('文件不存在');
}

// 获取文件MIME类型
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $filePath);
finfo_close($finfo);

// 设置适当的头部
header('Content-Type: ' . $mimeType);
header('Content-Disposition: attachment; filename="' . basename($filePath) . '"');
header('Content-Length: ' . filesize($filePath));
header('Cache-Control: no-cache, must-revalidate');
header('Pragma: no-cache');

// 禁用输出缓冲
if (ob_get_level()) ob_end_clean();

// 以二进制模式读取文件并输出
if ($handle = fopen($filePath, 'rb')) {
    while (!feof($handle) && (connection_status() == 0)) {
        print(fread($handle, 8192));
        flush();
    }
    fclose($handle);
}

exit;
?>

增加访问源检测,已解决

<?php
$allowedHosts = ['www.ximi.me', 'ximi.me'];

if (!isset($_SERVER['HTTP_REFERER']) || !in_array(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST), $allowedHosts)) {
    header('HTTP/1.0 403 Forbidden');
    exit('来源不合法禁止访问,Access forbidden');
}
?>


<?php
header('Access-Control-Allow-Origin: https://www.ximi.me'); // 仅允许特定域访问
?>


<?php
if (!isset($_SERVER['HTTP_ACCEPT']) || $_SERVER['HTTP_ACCEPT'] == '*/*') {
    header('HTTP/1.0 403 Forbidden');
    exit('检测到非法访问;Access forbidden');
}
?>


<?php
session_start();
$ip = $_SERVER['REMOTE_ADDR'];
if (!isset($_SESSION['last_request_time'][$ip])) {
    $_SESSION['last_request_time'][$ip] = time();
} else {
    $currentTime = time();
    $lastTime = $_SESSION['last_request_time'][$ip];
    
    if (($currentTime - $lastTime) < 5) { // 5秒内不允许多次请求
        header('HTTP/1.0 429 Too Many Requests');
        exit('Too many requests, please slow down.');
    } else {
        $_SESSION['last_request_time'][$ip] = $currentTime;
    }
}
?>
本站资源均为作者提供和网友推荐收集整理而来,仅供学习和研究使用,请在下载后24小时内删除,谢谢合作!
【PHP】防止文章附件被盗链,单文件解决方法|不死鸟资源网
【PHP】防止文章附件被盗链,单文件解决方法
此内容为免费阅读,请登录后查看
¥0
限时特惠
¥99
文章采用CC BY-NC-SA 4.0许可协议授权
免费阅读
THE END
点赞10 分享