我有一个PHP文件,唯一的工作是检查用户是否login+如果设置了会话variables,然后通过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"
更新2:如果我更改php文件更仔细检查variables:
<?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
login时,以及:
info: SESSION: exiting
当没有login。它应该按预期工作。
UPDATE3:
添加var_dump:
if(!$userInfo || !isset($_SESSION[$folder])) { var_dump($userInfo); var_dump($_SESSION[$folder]); //header('Location:login.php'); exit(); } echo "sending file";
当login时没有login和sending file
时,我得到NULL NULL。没有循环的回声。 iOS的行为就像加载的MP4,显示播放button,但没有video,除非我删除exit()
线。
UPDATE4:如果我用exit()replacedie(),效果相同。 用一个无意义的函数replace它来杀死脚本也有同样的效果。 出于某种原因,只有在请求mp4时才会进入if语句。
解决scheme:我必须将会话ID作为查询string传递给页面,然后手动进行设置。 这适用于我的使用情况,因为这个PHP页面不应该链接到其他页面,公开会话ID作为推介链接。 不是100%的理想,但它会桥接我,直到苹果推iOS修复。 哦,我删除了authConfig代码检查,因为这是多余的。 如果用户尚未login,则不能设置会话variables。
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;
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的任何请求? 或者使用自己的cookies /会话系统进行实验,看看他们的行为是否相同。 这就是我现在所能想到的。
来自苹果论坛的东西: https : //forums.developer.apple.com/thread/60688
Safari似乎只是添加那些路径不同于请求url路径的cookie。 但是这可以在IOS9上的其他浏览器上运行,因为这些浏览器可能会在域的根目录上创建cookie。
所以请尝试更改请求的路径。
尝试它(不死/退出):
<?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); }