Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用PHP防止AmazonS3上的热链接_Php_Amazon S3_Hotlinking - Fatal编程技术网

使用PHP防止AmazonS3上的热链接

使用PHP防止AmazonS3上的热链接,php,amazon-s3,hotlinking,Php,Amazon S3,Hotlinking,在我的网站上,我正在做一个图像保护部分,以降低AmazonS3的成本。因此,作为其中的一部分,我使用php为图像制作了反热链接(据我所知) 为了不那么明显,我设置了一个重写,将/711/video.mp4路由到cdn/711/video.mp4。这样,看起来就不会有PHP脚本了 RewriteRule ^cdn/([0-9a-zA-Z_]+)/([0-9a-zA-Z-\w.-]+)([\w.-]+)?$ media\.php\?id=$1/$2 [QSA,L] 上述系统工作正常,但问题是,当我

在我的网站上,我正在做一个图像保护部分,以降低AmazonS3的成本。因此,作为其中的一部分,我使用php为图像制作了反热链接(据我所知)

为了不那么明显,我设置了一个重写,将
/711/video.mp4
路由到
cdn/711/video.mp4
。这样,看起来就不会有PHP脚本了

RewriteRule ^cdn/([0-9a-zA-Z_]+)/([0-9a-zA-Z-\w.-]+)([\w.-]+)?$ media\.php\?id=$1/$2 [QSA,L]
上述系统工作正常,但问题是,当我直接加载图像时,图像的加载时间是
237ms
,当通过此PHP脚本加载图像时,加载时间是
1.65s


我已经分享了我的全部代码,因此如果有任何改进的机会,请指导我正确的方向,以便我可以进行相应的更改。

您的脚本比直接查询s3花费的时间更长的原因是您为图像请求增加了大量开销。您的Web服务器需要下载图像,然后将其转发给您的用户。这几乎肯定是你最大的瓶颈

我建议做的第一件事是使用。这仍然在引擎盖下使用
curl()
,但有一些优化,名义上可以提高性能。这还允许您将s3 bucket设置为“私有”,这将不需要隐藏S3URL

综上所述,防止与AWS热链接的推荐方法是使用cloudfront进行推荐人检查。AWS概述了如何做到这一点。

如果您不想重构您的基础架构,那么提高性能的最佳方法可能是实现本地缓存。最基本的情况是,这看起来像这样:

    $cacheDir = '/path/to/a/local/directory/';
    $cacheFileName = str_replace('/', '_', $file);

    if (file_exists($cacheDir . $cacheFileName)){
        $mime = mime_content_type($cacheDir . $cacheFileName);
        $content = file_get_contents($cacheDir . $cacheFileName);
    } else {
        $url = 'https://s3.example.com';

        $s3 = "$url/$file";

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $s3);
        curl_setopt($ch, CURLOPT_HEADER, 1);
        curl_setopt($ch, CURLOPT_NOBODY, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        $results = explode("\n", trim(curl_exec($ch)));
        foreach($results as $line) {
            if (strtok($line, ':') == 'Content-Type') {
                $parts = explode(":", $line);
                $mime = trim($parts[1]);
            }
        }
        $content = file_get_contents($s3);
        file_put_contents($cacheDir . $cacheFileName, $content);
    }

    header("Content-type: $mime");
    echo $content;

这将在本地存储文件的副本,这样服务器就不需要每次请求时都从s3下载它。这将在一定程度上减少您的开销,尽管它不如纯粹基于AWS的解决方案。使用此解决方案,您还必须添加中断缓存、定期使缓存过期等方法。重申一下,您不应该只是将其复制/粘贴到生产环境中,这是一个开始,但更像是一个概念验证,而不是生产代码。

$\u服务器['HTTP\u REFERER']
不可靠。请看:您可能已经共享了所有代码,但您谈论的是图像,而路线建议使用视频,为什么你需要使用cURL?我目前在该服务器上有图像和视频,我上面分享的代码是为了了解我正在尝试做什么,cURL用于从原始S3服务器获取外部文件的mime类型,图像/视频托管在该服务器上。你为什么不完全去掉cURL,只需要两个PHP脚本,一个用于图像,另一个用于视频。当然,他们可以在第三个文件中共享一些代码。我假设您正在使用HTTP协议来读取该文件,因为PHP脚本位于图像和视频之外的另一台服务器上。这就解释了缓慢的原因。这些映像正在通过第二台服务器传递,而不是来自一台服务器。如果PHP脚本在同一台服务器上,那么应该使用文件的路径,而不是URL。如果计划通过另一台服务器对所有流量进行隧道传输,为什么要使用S3?这违背了使用CDN的目的
RewriteRule ^cdn/([0-9a-zA-Z_]+)/([0-9a-zA-Z-\w.-]+)([\w.-]+)?$ media\.php\?id=$1/$2 [QSA,L]
    $cacheDir = '/path/to/a/local/directory/';
    $cacheFileName = str_replace('/', '_', $file);

    if (file_exists($cacheDir . $cacheFileName)){
        $mime = mime_content_type($cacheDir . $cacheFileName);
        $content = file_get_contents($cacheDir . $cacheFileName);
    } else {
        $url = 'https://s3.example.com';

        $s3 = "$url/$file";

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $s3);
        curl_setopt($ch, CURLOPT_HEADER, 1);
        curl_setopt($ch, CURLOPT_NOBODY, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        $results = explode("\n", trim(curl_exec($ch)));
        foreach($results as $line) {
            if (strtok($line, ':') == 'Content-Type') {
                $parts = explode(":", $line);
                $mime = trim($parts[1]);
            }
        }
        $content = file_get_contents($s3);
        file_put_contents($cacheDir . $cacheFileName, $content);
    }

    header("Content-type: $mime");
    echo $content;