如果 URL 具有某些文件扩展名,RackSpace Cloud 会删除 $_SESSION

发布于 2024-08-20 18:52:42 字数 2041 浏览 6 评论 0原文

情况

我正在使用传统的 LAMP 堆栈(RackSpace 的云同时具有 Windows 和 LAMP 堆栈)在 RackSpace 云上为客户创建一个视频培训站点。我在此网站上提供的视频和其他媒体文件需要受到保护,因为我的客户需要付费才能访问它们。没有 DRM 或类似的有趣业务,本质上我们将文件存储在 Web 根目录之外,并使用 PHP 来验证用户的身份,然后才能使用 mod_rewrite 通过 PHP 运行请求来访问文件。

假设用户请求此 URL 上的文件:

http://www.example.com/uploads/preview_image/29.jpg

我正在使用 mod_rewrite 将该 url 重写为:

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 支持验证了此行为,他们表示对此无能为力。

The Situation

I am creating a video training site for a client on the RackSpace Cloud using the traditional LAMP stack (RackSpace's cloud has both Windows and LAMP stacks). The videos and other media files I'm serving on this site need to be protected as my client charges money for access to them. There is no DRM or funny business like that, essentially we store the files outside of the web root and use PHP to authenticate user's before they are able to access the files by using mod_rewrite to run the request through PHP.

So let's say the user requests a file at this URL:

http://www.example.com/uploads/preview_image/29.jpg

I am using mod_rewrite to rewrite that url to:

http://www.example.com/files.php?path=%2Fuploads%2Fpreview_image%2F29.jpg

Here is a simplified version of the files.php script:

<?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();

?>

The Problem

Let me start by saying this works perfectly for me. On local test machines it works like a charm. However once deployed to the cloud it stops working. After some debugging it turns out that if a request to the cloud has certain file extensions like .JPG, .PNG, or .SWF (i.e. extensions of typically static media files.) the request is routed to a cache system called Varnish. The end result of this routing is that by the time this whole process makes it to my PHP script the session is not present.

If I change the extension in the URL to .PHP or if I even add a query parameter Varnish is bypassed and the PHP script can get the session. No problem right? I'll just add a meaningless query parameter to my requests!

Here is the rub: The media files I am serving through this system are being requested through compiled SWF files that I have zero control over. They are generated by third-party software and I have no hope of adding or changing the URLs that they request.

Are there any other options I have on this?

Update: I should note that I have verified this behavior with RackSpace support and they have said there is nothing they can do about it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

对你而言 2024-08-27 18:52:42

如果请求的 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");

And:
我会将 exit(); 命令放在第一个 header() 语句之后,以确保脚本的其余部分不会执行。 header() 仅发送标头。

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

If the requesting flash app is following redirects, I would try to answer with a redirect on the first request and rewrite the second one, e.g.

GET .../29.jpg

to

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

Then your r.php delivers the file on the second request.

If not (btw. always), I would explicitly send headers along with delivering the static files that Varnish accepts and acts accordingly, something like

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");

And:
I would place the exit(); command after your first header() statement to be sure the rest of the script is not executed. header() sends just headers.

I find it also more reliable to use ob_start() as whitespace in your PHP file may lead to annoying errors when adding headers.

薄暮涼年 2024-08-27 18:52:42

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

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

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

I have the same situation, and I've contacted Rackspace hoping for a better answer.

I got one! They've put together a FAQ outlining half a dozen ways to bypass/modify the caching:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文