我有一个PHP文件,唯一的工作是检查用户是否登录+如果设置了会话变量,然后通过nginx X-Sendfile传递文件。它可以在任何桌面浏览器上完美运行,以前可以在任何移动浏览器上运行 - 但在任何只有mp4的ios 10浏览器上都会失败。对我来说没什么意义的是,如果我评论die()
行,它会按预期工作,但PHP代码应该永远不会进入该行。
<?php
require_once('authConfig.php');
$userInfo = $auth0->getUser();
session_start();
include('cururl.php');
$murl = curPageURL();
parse_str($murl, $result);
$filename=$result['file'];
$folder=$result['folder'];
if (!$userInfo || !isset($_SESSION[$folder])) {
header('Location:login.php');
die();
}
$file="/var/www/uploads/" . $folder . "/" . $filename;
$aliasedFile = '/protected/' . $folder .'/' . $filename;
$realFile = $file;
header('Cache-Control: public, must-revalidate');
header('Pragma: no-cache');
header('Content-Type: ' . mime_content_type($file));
header('Content-Length: ' .(string)(filesize($realFile)) );
header('X-Accel-Redirect: ' . $aliasedFile);
exit;
?>
我可以通过将代码更改为:
来确认$_SESSION[$folder]
实际已设置
if(isset($_SESSION[$folder])){
echo "OK";
die();
}
更新:这是来自iPhone的访问日志。它应该有权访问该文件。
10.0.0.1 forwarded for ..., 10.0.0.1 - - [16/Sep/2016:10:07:20 -0400] "GET /xfiles.php?&file=001.mp4&folder=NNx6659rvB HTTP/1.0" 200 1944706 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_1 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/14A403 Safari/602.1"
10.0.0.1 forwarded for ..., 10.0.0.1 - - [16/Sep/2016:10:07:21 -0400] "GET /xfiles.php?&file=001.mp4&folder=NNx6659rvB HTTP/1.0" 302 0 "https://www.sonoclipshare.com/xfiles.php?&file=001.mp4&folder=NNx6659rvB" "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_1 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/14A403 Safari/602.1"
10.0.0.1 forwarded for ..., 10.0.0.1 - - [16/Sep/2016:10:07:21 -0400] "GET /login.php HTTP/1.0" 200 4166 "https://www.sonoclipshare.com/xfiles.php?&file=001.mp4&folder=NNx6659rvB" "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_1 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/14A403 Safari/602.1"
UPDATE2: 如果我更改php文件以更仔细地检查变量:
<?php
require_once('authConfig.php');
$userInfo = $auth0->getUser();
session_start();
include('cururl.php');
$murl = curPageURL();
parse_str($murl, $result);
$filename=$result['file'];
$folder=$result['folder'];
print("info: $userInfo <br>SESSION: $_SESSION[$folder] <br>");
if(!$userInfo || !isset($_SESSION[$folder])) {
print("exiting");
}else {
print("sending file");
}
我得到的结果是:
info: Array
SESSION: NNc6659rvB
sending file
登录时,并且:
info:
SESSION:
exiting
未登录时。应按预期工作。
UPDATE3:
添加var_dump:
if(!$userInfo || !isset($_SESSION[$folder])) {
var_dump($userInfo);
var_dump($_SESSION[$folder]);
//header('Location:login.php');
exit();
}
echo "sending file";
我没有登录时为NULL NULL,登录时为sending file
。循环中没有回显。 iOS就像加载mp4,显示播放按钮但没有视频,除非我删除exit()
行。
UPDATE4: 如果我用exit()替换die(),效果相同。用无意义函数替换它以杀死脚本也具有相同的效果。出于某种原因,当我仅请求mp4时,它会进入if语句。
解决方案:我必须将会话ID作为查询字符串传递给页面,然后手动设置。这适用于我的用例,因为这个php页面不应该链接到其他页面,将会话ID作为引用链接公开。不是100%理想,但它会帮助我解决问题,直到Apple推出iOS修复程序。哦,我删除了authConfig代码检查,因为这是多余的。如果用户尚未登录,则无法设置会话变量。
include('cururl.php');
$murl = curPageURL();
parse_str($murl, $result);
$filename=$result['file'];
$folder=$result['folder'];
$session_id=$result['session_id'];
session_id($session_id);
session_start();
if(empty($_SESSION[$folder])) {
echo "redirecting";
exit(header("Location: login.php"));
}
$file="/var/www/uploads/" . $folder . "/" . $filename;
$aliasedFile = '/protected/' . $folder .'/' . $filename; //this is the nginx alias of the file path
$realFile = $file; //this is the physical file path
header('Cache-Control: public, must-revalidate');
header('Pragma: no-cache');
header('Content-Type: ' . mime_content_type($file));
header('Content-Length: ' .(string)(filesize($realFile)) );
header('X-Accel-Redirect: ' . $aliasedFile);
exit;
答案 0 :(得分:3)
Ilmari告诉你情况:请求mp4时没有设置$_SESSION[$folder]
。这意味着iOS不会发回sessionID。
删除die
将“修复”问题,因为代码只是继续,但它是一个红色的鲱鱼。可能会发出“重定向标头”,但如果您不退出,则会有其他标头基本上使重定向请求无效。发出重定向标题后始终有退出(或死亡)。
您需要检查的是,是否为这些请求设置了$ _SESSION。您不会在Apache / NGNIX访问日志中找到它,但需要自己记录。最简单的情况是将file_put_contents('\tmp\debug.log\, print_r($_SESSION, true));
添加到代码中。 (将覆盖每次运行,如果要追加则使用fopen)。然后追回以查看使用相同日志记录发送(或未发送)的cookie。但有些事情并没有发送sessionID。
至于解决方案:这很棘手。在它正确修复之前,也许你可以使用IP地址?不是那么可靠(事实上,非常不可靠),但如果用户使用特定的IP登录,那么允许来自该IP的任何请求?或者使用您自己的cookie /会话系统进行实验,看看它们的行为是否相同。这就是我现在所能想到的。
来自Apple论坛的内容:https://forums.developer.apple.com/thread/60688
Safari似乎只添加路径与请求网址路径不同的Cookie。但是这可能会在IOS9上的其他浏览器上运行,因为这些浏览器可能会在域的根目录上创建cookie。
因此,请尝试更改请求的路径。
答案 1 :(得分:1)
尝试它(没有死/退出):
<?php
require_once 'authConfig.php'; // ok this *_once
$userInfo = $auth0->getUser();
session_start(); // why this line after get userinfo? probably this line must be place before including authConfig.php
if (!$userInfo || !isset($_SESSION[$folder])) {
header('Location:login.php');
} else {
include 'cururl.php'; // why this not *_once?
$murl = curPageURL();
parse_str($murl, $result);
$filename = $result['file'];
$folder = $result['folder'];
$file = '/var/www/uploads/' . $folder . '/' . $filename;
$aliasedFile = '/protected/' . $folder .'/' . $filename;
$realFile = $file;
header('Cache-Control: public, must-revalidate');
header('Pragma: no-cache');
header('Content-Type: ' . mime_content_type($file));
header('Content-Length: ' . filesize($realFile)); // dont require cast to string because concatenation
header('X-Accel-Redirect: ' . $aliasedFile);
}