尝试通过X-Sendfile传送mp4时,iOS 10不会发送会话ID

Ult*_*lly 10 php x-sendfile nginx ios10

我有一个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;
?>
Run Code Online (Sandbox Code Playgroud)

我可以$_SESSION[$folder]通过将代码更改为:

if(isset($_SESSION[$folder])){
   echo "OK";
   die();
} 
Run Code Online (Sandbox Code Playgroud)

更新:这是来自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"
Run Code Online (Sandbox Code Playgroud)

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");
}
Run Code Online (Sandbox Code Playgroud)

我得到的结果是:

info: Array
SESSION: NNc6659rvB
sending file
Run Code Online (Sandbox Code Playgroud)

登录时,和:

info:
SESSION:
exiting
Run Code Online (Sandbox Code Playgroud)

什么时候没有登录.它应该按预期工作.

UPDATE3:
添加var_dump:

if(!$userInfo || !isset($_SESSION[$folder])) {
        var_dump($userInfo);
        var_dump($_SESSION[$folder]);
        //header('Location:login.php');
        exit();
}
echo "sending file";
Run Code Online (Sandbox Code Playgroud)

我没有登录和sending file登录时获得NULL NULL .循环中没有回显.iOS就像加载mp4,显示播放按钮但没有视频,除非我删除该exit()行.

UPDATE4:如果我用exit()替换die(),效果相同.用无意义函数替换它以杀死脚本也具有相同的效果.出于某种原因,当我仅请求mp4时它会进入if语句.

解决方案:我必须将会话ID作为查询字符串传递给页面,然后手动设置.这适用于我的用例,因为这个php页面不应该链接到其他页面,将会话ID作为引用链接公开.不是百分之百的理想,但它会帮助我,直到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;
Run Code Online (Sandbox Code Playgroud)

Rob*_*bie 4

Ilmari 已经告诉您情况:$_SESSION[$folder]请求 mp4 时未设置。这意味着 iOS 不会发回 sessionID。

删除die将“解决”问题,因为代码只是继续,但这是一个转移注意力的事情。它可能会发出“重定向标头”,但如果您不退出,则会出现其他标头,这些标头基本上会使重定向请求无效。在发出重定向标头后始终有一个退出(或死亡)。

您需要检查的是是否为这些请求设置了 $_SESSION。您不会在 Apache/NGNIX 访问日志中找到该信息,但需要自己记录。最简单的情况是添加file_put_contents('\tmp\debug.log\, print_r($_SESSION, true));到代码中。(将覆盖每次运行,如果要追加,请使用 fopen)。然后回溯查看使用相同的日志记录正在发送(或未发送)哪些 cookie。但有些东西没有发送 sessionID。

至于解决方案:这很棘手。在正确修复之前,也许您可​​以使用 IP 地址?不太可靠(事实上,非常不可靠),但是如果用户使用特定 IP 登录,那么允许来自该 IP 的任何请求吗?或者使用您自己的 cookie/会话系统进行实验,看看它们的行为是否相同。目前我能想到的就这么多。


来自苹果论坛的内容:https://forums.developer.apple.com/thread/60688

Safari 似乎只添加那些路径与请求 url 路径不同的 cookie。但这似乎适用于 IOS9 上的其他浏览器,因为这些浏览器可能会在域的根目录上创建 cookie。

所以尝试改变请求的路径。