首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 防盜鏈實戰:三種核心策略與代碼實現

     編輯:PHP 相關知識

防盜鏈核心原理

防盜鏈的本質是 驗證 HTTP Referer 標頭,判斷請求來源是否為授權域名。PHP 通過 $_SERVER['HTTP_REFERER'] 獲取來源地址,配合白名單機制實現訪問控制。

⚠ 重要提醒: Referer 可被偽造或被瀏覽器/代理屏蔽(隱私模式、安全軟體)。生產環境建議結合 Token 簽名 URL、Nginx/Apache 層面限制 多層防護。PHP 層面僅作為應用層補充。

策略一:簡單域名黑名單攔截

適用場景:已知惡意盜鏈源,需快速封禁。

<?php
// block_referer.php
$blockedDomains = ['qq.com', 'malicious-site.com', 'spammer.net'];
$referer = $_SERVER['HTTP_REFERER'] ?? '';

$blocked = false;
foreach ($blockedDomains as $domain) {
    if (stripos($referer, $domain) !== false) {
        $blocked = true;
        break;
    }
}

if ($blocked) {
    // 返回 404 而非 403,隱藏資源存在性
    header('HTTP/1.1 404 Not Found');
    exit('Resource not found');
}

// 正常輸出文件 (示例為音頻)
$file = __DIR__ . '/media/song.mp3';
if (file_exists($file)) {
    header('Content-Type: audio/mpeg');
    header('Content-Length: ' . filesize($file));
    header('Accept-Ranges: bytes'); // 支援斷點續傳
    readfile($file);
} else {
    header('HTTP/1.1 404 Not Found');
}
?>

策略二:白名單授權模式 (推薦)

原則:默認拒絕,僅允許名單內域名。更安全,適合保護付費資源、內部素材。

<?php
// auth_download.php
$config = [
    'allowed_referers' => [
        'https://www.myapp.com',
        'https://app.myapp.com',
        'https://localhost', // 開發環境
    ],
    'resource_map' => [
        'video1' => '/data/videos/course_01.mp4',
        'pdf1'   => '/data/docs/manual.pdf',
        'img1'   => '/data/images/secret.jpg',
    ],
    'default_404' => '/assets/404.html'
];

$referer = $_SERVER['HTTP_REFERER'] ?? '';
$resourceKey = $_GET['res'] ?? '';

// 1. 驗證 Referer
$allowed = false;
foreach ($config['allowed_referers'] as $allowedDomain) {
    // 使用 parse_url 精確匹配域名,避免子域名繞過
    $refHost = parse_url($referer, PHP_URL_HOST) ?? '';
    $allowHost = parse_url($allowedDomain, PHP_URL_HOST);
    if (strcasecmp($refHost, $allowHost) === 0) {
        $allowed = true;
        break;
    }
}

// 2. 驗證資源合法性
if (!$allowed || !isset($config['resource_map'][$resourceKey])) {
    header('Location: ' . $config['default_404']);
    exit;
}

// 3. 安全輸出文件
$filePath = $config['resource_map'][$resourceKey];
// 防止目錄遍歷攻擊
$filePath = realpath($filePath);
if ($filePath === false || strpos($filePath, realpath('/data/')) !== 0) {
    header('HTTP/1.1 404 Not Found');
    exit;
}

// 輸出頭部
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $filePath);
finfo_close($finfo);

header('Content-Type: ' . $mime);
header('Content-Length: ' . filesize($filePath));
header('Content-Disposition: inline; filename="' . basename($filePath) . '"');
header('Cache-Control: private, max-age=3600'); // 僅客戶端緩存 1 小時
readfile($filePath);
?>

策略三:帶防盜鏈 Token 的簽名 URL (最高安全級別)

原理:生成帶有過期時間和簽名的一次性下載鏈接,無需依賴 Referer。

<?php
// token_generator.php (在授權頁面調用生成下載鏈接)
function generateSecureUrl($resourceId, $secretKey, $expireMinutes = 30) {
    $expire = time() + $expireMinutes * 60;
    $data = $resourceId . '|' . $expire;
    $signature = hash_hmac('sha256', $data, $secretKey);
    return "download.php?res={$resourceId}&exp={$expire}&sig={$signature}";
}

// download.php (驗證 Token)
$secretKey = 'your_very_long_random_secret_key_here'; // 必須與生成端一致
$resourceId = $_GET['res'] ?? '';
$expire = (int)($_GET['exp'] ?? 0);
$signature = $_GET['sig'] ?? '';

if (time() > $expire) {
    die('鏈接已過期');
}

$data = $resourceId . '|' . $expire;
$expectedSig = hash_hmac('sha256', $data, $secretKey);

// 使用 hash_equals 防時序攻擊
if (!hash_equals($expectedSig, $signature)) {
    die('無效簽名');
}

// 此處接資源映射與輸出邏輯 (同策略二)
// ...
?>

Web 服務器層面防盜鏈 (效能最佳)

強烈建議 在 Nginx/Apache 層面實現,避免 PHP 進程開銷:

Nginx 配置

location ~* \.(mp4|mp3|pdf|zip|jpg|png)$ {
    valid_referers none blocked *.myapp.com myapp.com;
    if ($invalid_referer) {
        return 403; # 或 rewrite 到預覽圖/404 頁面
        # rewrite ^/ https://myapp.com/403.html redirect;
    }
}

Apache (.htaccess)

RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?myapp\.com [NC]
RewriteRule \.(mp4|mp3|pdf|zip|jpg|png)$ - [F,NC]
# 或重定向: RewriteRule \.(mp4|mp3|pdf|zip)$ /403.html [R=302,L]

總結與選型建議

方案安全性效能適用場景
PHP 黑名單低中臨時應急、已知惡意源
PHP 白名單中中內部系統、會員資源、無法改服務器配置
PHP Token 簽名高中低付費下載、私密文件、需控制下載次數/時效
Nginx/Apache 原生中高極高生產環境首選,靜態資源防盜鏈標準做法

最佳實踐:Nginx 做第一道防線 (靜態資源) + PHP Token 做第二道防線 (動態業務資源)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved