4

情况

我正在使用传统的 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 支持验证了这种行为,他们说他们对此无能为力。

4

2 回答 2

2

如果请求的 Flash 应用程序遵循重定向,我会尝试在第一个请求上使用重定向来回答并重写第二个请求,例如

GET .../29.jpg

header("Status: 302 Moved temporarily");
header("Location: .../r.php?i=29.jpg&random=872938729348");

然后您的 r.php 在第二个请求中提供文件。

如果不是(顺便说一句。总是),我会显式发送标头以及提供 Varnish 接受并采取相应措施的静态文件,例如

header("Cache-Control: no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");

并且:我会将exit();命令放在您的第一header()条语句之后,以确保不执行脚本的其余部分。header()只发送标题。

我发现在你的 PHP 文件中使用空格也更可靠,ob_start()在添加标题时可能会导致恼人的错误。

于 2010-02-12T08:29:42.400 回答
0

我有同样的情况,我已经联系了 Rackspace 希望得到更好的答案。

我有一个!他们整理了一个常见问题解答,概述了绕过/修改缓存的六种方法:

http://cloudsites.rackspacecloud.com/index.php/How_can_I_bypass_the_cache%3F

于 2010-05-26T17:07:08.853 回答