PHP Proxy ảnh bảo mật: Giải pháp tải ảnh từ xa an toàn, có cache

Trong một số trường hợp, bạn cần tải ảnh từ URL bên ngoài và hiển thị trên website của mình mà không vi phạm chính sách CORS, đồng thời muốn trình duyệt người dùng cache ảnh để tăng tốc độ tải trang. Bài viết này hướng dẫn bạn cách xây dựng một proxy ảnh đơn giản nhưng an toàn, chống SSRF, chống abuse và dễ triển khai với PHP.

PHP Proxy ảnh bảo mật: Giải pháp tải ảnh từ xa an toàn, có cache

1. Tạo file view.php trong thư mục proxy/

<?php
// Cấu hình whitelist host
$allowed_hosts = ['i.imgur.com', 'cdn.example.com'];

// Lấy URL từ query string
$url = isset($_GET['url']) ? $_GET['url'] : '';
if (!$url) {
    http_response_code(400);
    exit('Missing image URL');
}

// Kiểm tra định dạng URL
if (!filter_var($url, FILTER_VALIDATE_URL)) {
    http_response_code(400);
    exit('Invalid URL');
}

// Kiểm tra host có được phép không
$host = parse_url($url, PHP_URL_HOST);
if (!in_array($host, $allowed_hosts, true)) {
    http_response_code(403);
    exit('Host not allowed');
}

// Chống SSRF bằng cách kiểm tra IP đích
$ip = gethostbyname($host);
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
    http_response_code(403);
    exit('Private IP access denied');
}

// Sử dụng cURL để tải ảnh
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
$data = curl_exec($ch);
$content_type = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
$content_length = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

// Kiểm tra HTTP code
if ($http_code !== 200 || !$data) {
    http_response_code(404);
    exit('Image not found');
}

// Kiểm tra MIME
if (strpos($content_type, 'image/') !== 0) {
    http_response_code(415);
    exit('Invalid image type');
}

// Giới hạn dung lượng (tối đa 5MB)
if ($content_length > 5 * 1024 * 1024) {
    http_response_code(413);
    exit('Image too large');
}

// Gửi header để cache trên trình duyệt trong 30 ngày
header('Content-Type: ' . $content_type);
header('Content-Length: ' . strlen($data));
header('Cache-Control: public, max-age=2592000');
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 2592000) . ' GMT');
echo $data;

2. Cách sử dụng proxy ảnh

Bạn có thể sử dụng công cụ này để tải ảnh thông qua URL như sau:

https://yourdomain.com/proxy/view.php?url=https://i.imgur.com/example.jpg

Lưu ý:

  • Chỉ những host nằm trong mảng $allowed_hosts mới được phép tải ảnh.
  • Ảnh phải là định dạng hợp lệ và không vượt quá giới hạn dung lượng (5MB mặc định).

3. Tối ưu thêm bằng Cloudflare (tùy chọn)

Nếu bạn dùng Cloudflare, bạn có thể:

  • Bật cache cho thư mục /proxy/
  • Thêm Page Rules để cache kết quả proxy trên CDN
  • Giảm tải cho server và tăng tốc hiển thị ảnh

Tổng kết

Nếu bạn cần mở rộng thêm các tính năng như:

  • Bộ nhớ đệm ảnh vào ổ đĩa
  • Thêm xác thực API key
  • Tự động scale ảnh trước khi trả về

… thì bạn có thể tiếp tục phát triển dựa trên nền tảng proxy an toàn này.

Bình luận


  • Không có bình luận.

Init Toolbox

Nhấn Ctrl + \ trên máy tính, hoặc vuốt sang trái ở bất kỳ đâu trên mobile.

Đăng nhập





Đang tải...