情况
我正在使用传统的 LAMP 堆栈(RackSpace 的云同时具有 Windows 和 LAMP 堆栈)为 RackSpace 云上的客户创建一个视频培训站点。我在此站点上提供的视频和其他媒体文件需要受到保护,因为我的客户会为访问它们而收费。没有 DRM 或类似的有趣业务,本质上我们将文件存储在 Web 根目录之外,并使用 PHP 来验证用户的身份,然后他们才能通过使用 mod_rewrite 通过 PHP 运行请求来访问文件。
所以假设用户在这个 URL 请求一个文件:
http://www.example.com/uploads/preview_image/29.jpg
我正在使用 mod_rewrite 将该网址重写为:
http://www.example.com/files.php?path=%2Fuploads%2Fpreview_image%2F29.jpg
这是 files.php 脚本的简化版本:
<?php
// Setups the environment and sets $logged_in
// This part requires $_SESSION
require_once('../../includes/user_config.php');
if (!$logged_in) {
// Redirect non-authenticated users
header('Location: login.php');
}
// This user is authenticated, continue
$content_type = "image/jpeg";
// getAbsolutePathForRequestedResource() takes
// a Query Parameter called path and uses DB
// lookups and some string manipulation to get
// an absolute path. This part doesn't have
// any bearing on the problem at hand
$file_path = getAbsolutePathForRequestedResource($_GET['path']);
// At this point $file_path looks something like
// this: "/path/to/a/place/outside/the/webroot"
if (file_exists($file_path) && !is_dir($file_path)) {
header("Content-Type: $content_type");
header('Content-Length: ' . filesize($file_path));
echo file_get_contents($file_path);
} else {
header('HTTP/1.0 404 Not Found');
header('Status: 404 Not Found');
echo '404 Not Found';
}
exit();
?>
问题
首先让我说这对我来说非常有效。在本地测试机器上,它就像一个魅力。但是,一旦部署到云端,它就会停止工作。经过一些调试,事实证明,如果对云的请求具有某些文件扩展名,如 .JPG、.PNG 或 .SWF(即通常为静态媒体文件的扩展名),则该请求将被路由到名为 Varnish 的缓存系统。此路由的最终结果是,当整个过程到达我的 PHP 脚本时,会话不存在。
如果我将 URL 中的扩展名更改为 .PHP,或者我什至添加了一个查询参数 Varnish 被绕过并且 PHP 脚本可以获取会话。没问题吧?我将在我的请求中添加一个无意义的查询参数!
这就是问题所在:我通过这个系统提供的媒体文件是通过我零控制的已编译 SWF 文件请求的。它们是由第三方软件生成的,我不希望添加或更改它们请求的 URL。
我对此还有其他选择吗?
更新:我应该注意,我已经通过 RackSpace 支持验证了这种行为,他们说他们对此无能为力。