2016-09-16 69 views
10

我有一个PHP文件,唯一的工作是检查用户是否登录+如果设置了会话变量,然后通过文件传递文件nginx X-Sendfile。它可以在任何桌面浏览器上完美工作,并且可以在任何移动浏览器上正常运行 - 但只能在任何带有mp4的ios 10浏览器上运行。对我来说毫无意义的是,如果我评论die()这一行,它的工作方式和预期的一样,但是php代码甚至不应该进入该行。当试图通过X-Sendfile发送mp4时,iOS 10不会发送会话ID

<?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

我组合了条件,但问题依然存在: 'if(!$ userInfo ||!isset($ _ SESSION [$ folder])){header('Location:login.php');退出();}' – UltrasoundJelly

+0

如果我删除'die()/ exit()',重定向不起作用,但文件传递得很好。 – UltrasoundJelly

+1

未执行的代码无法生效。很明显,如果if(!isset($ _ SESSION [$ folder]))块中的内容有效,那么你必须接收一个带有$ _SESSION [$ folder]'unset的请求。由于某种原因,iOS可能会发送* 2个*文件请求?你真的看过你的请求日志吗? (你有请求日志记录启用,对不对?) –

回答

3

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 /会话系统进行实验,看看它们的行为是否相同。这就是我现在所能想到的。从Apple论坛


东西:https://forums.developer.apple.com/thread/60688

Safari浏览器似乎只增加这些Cookie的路径是从请求URL路径的不同。但是这可能会在IOS9上的其他浏览器上工作,因为它们可能会在域的根目录上创建cookie。

因此,请尝试更改请求的路径。

+0

你是对的。请求mp4时,我得到一个空的会话变量。但为什么不用jpgs呢? – UltrasoundJelly

+0

后续问题:你能详细说明_changing request_的路径吗? – UltrasoundJelly

+0

尝试使用setcookie来验证用户对数据库,它看起来像我不能读回到服务器。缺少选项。 – UltrasoundJelly

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); 
} 
相关问题