简体   繁体   English

如果URL具有某些文件扩展名,则RackSpace Cloud剥离$ _SESSION

[英]RackSpace Cloud Strips $_SESSION if URL Has Certain File Extensions

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). 我正在使用传统的LAMP堆栈(RackSpace的云同时具有Windows和LAMP堆栈)在RackSpace云上为客户端创建一个视频培训站点。 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. 没有像这样的DRM或有趣的事情,实质上,我们将文件存储在Web根目录之外,并使用PHP验证用户的身份,然后用户才能使用mod_rewrite通过PHP运行请求来访问文件。

So let's say the user requests a file at this URL: 假设用户在此URL请求文件:

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

I am using mod_rewrite to rewrite that url to: 我正在使用mod_rewrite将该URL重写为:

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

Here is a simplified version of the files.php script: 这是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();

?>

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 (ie extensions of typically static media files.) the request is routed to a cache system called Varnish. 经过一些调试后,结果发现,如果对云的请求具有某些文件扩展名,例如.JPG,.PNG或.SWF(即通常为静态媒体文件的扩展名),则该请求将路由到一个名为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. 这种路由的最终结果是,当整个过程进入我的PHP脚本时,该会话就不存在了。

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. 如果我将URL中的扩展名更改为.PHP或什至添加了查询参数,那么Varnish将被绕过,PHP脚本可以获取会话。 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. 麻烦之处是:我通过该系统提供的媒体文件是通过对我具有零控制权的已编译SWF文件请求的。 They are generated by third-party software and I have no hope of adding or changing the URLs that they request. 它们是由第三方软件生成的,我不希望添加或更改它们所请求的URL。

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. 更新:我应该注意,我已经在RackSpace支持下验证了此行为,他们说他们对此无能为力。

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, eg 如果请求的Flash应用程序正在执行重定向,那么我将尝试对第一个请求进行重定向并重写第二个请求,例如

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. 然后,您的r.php会在第二个请求中传递文件。

If not (btw. always), I would explicitly send headers along with delivering the static files that Varnish accepts and acts accordingly, something like 如果不是(总是如此),我将显式发送标头,并提供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: I would place the exit(); 并且:我将放置exit(); command after your first header() statement to be sure the rest of the script is not executed. 在您的第一个header()语句之后输入命令,以确保脚本的其余部分没有执行。 header() sends just headers. header()仅发送标题。

I find it also more reliable to use ob_start() as whitespace in your PHP file may lead to annoying errors when adding headers. 我发现使用ob_start()也更加可靠,因为PHP文件中的空格可能会在添加标头时导致令人讨厌的错误。

I have the same situation, and I've contacted Rackspace hoping for a better answer. 我也有同样的情况,我已经联系了Rackspace,希望得到更好的答案。

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 http://cloudsites.rackspacecloud.com/index.php/How_can_I_bypass_the_cache%3F

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM