iOS 10 尝试通过 X-Sendfile 传送 mp4 时不会发送会话 ID
iOS 10 won't send session ID when trying to deliver mp4 via X-Sendfile
我有一个 PHP 文件,它的唯一工作是检查用户是否登录+是否设置了会话变量,然后通过 nginx X-Sendfile 传送文件。它在任何桌面浏览器上都能完美运行,之前在任何移动浏览器上运行 - 但在任何 ios 10 浏览器上仅支持 mp4 时会失败。对我来说意义不大的是,如果我评论 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 文件以更仔细地检查变量:
<?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
未登录时。它应该按预期工作。
更新 3:
添加 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()
行。
更新4:
如果我用 exit() 替换 die(),效果相同。换成一个杀脚本的废话函数也有同样的效果。出于某种原因,当我仅请求 mp4 时它进入 if 语句。
解决方案:我必须将会话 ID 作为查询字符串传递给页面,然后手动设置它。这对我的用例很有效,因为这个 php 页面不应该 link 到其他页面,将会话 ID 公开为引用 link。不是 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;
试一试(没有die/exit):
<?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);
}
Ilmari 已告诉您情况:请求 mp4 时未设置 $_SESSION[$folder]
。这意味着 iOS 没有发送回 sessionID。
删除 die
将 "fix" 问题,因为代码只是继续,但这是一个转移注意力的问题。它可能会发出一个 "redirect header",但如果你不退出,将会有其他 headers 基本上使重定向请求无效。发出重定向 header.
后总是有一个退出(或死亡)
您需要检查的是是否为这些请求设置了 $_SESSION。您不会在 Apache/NGNIX 访问日志中找到它,但需要自己记录。最简单的情况是将 file_put_contents('\tmp\debug.log\, print_r($_SESSION, true));
添加到代码中。 (将覆盖每个 运行,如果要追加,请使用 fopen)。然后回头看看使用相同的日志记录正在发送(或未发送)哪些 cookie。但是有些东西没有发送 sessionID。
至于解决方案:这很棘手。在正确修复之前,也许您可以使用 IP 地址?不太可靠(事实上,非常不可靠),但如果用户使用特定 IP 登录,那么允许来自该 IP 的任何请求?或者使用您自己的 cookies / session 系统进行实验,看看它们的行为是否相同。暂时能想到的就这些了
来自 Apple 论坛的内容:https://forums.developer.apple.com/thread/60688
Safari seems to be only adding those cookies whose path is different from the request url path. But this seesm to work on other browsers on IOS9 as these may be creating the cookies on the root of the domain.
所以尝试改变请求的路径。
我有一个 PHP 文件,它的唯一工作是检查用户是否登录+是否设置了会话变量,然后通过 nginx X-Sendfile 传送文件。它在任何桌面浏览器上都能完美运行,之前在任何移动浏览器上运行 - 但在任何 ios 10 浏览器上仅支持 mp4 时会失败。对我来说意义不大的是,如果我评论 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 文件以更仔细地检查变量:
<?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
未登录时。它应该按预期工作。
更新 3:
添加 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()
行。
更新4: 如果我用 exit() 替换 die(),效果相同。换成一个杀脚本的废话函数也有同样的效果。出于某种原因,当我仅请求 mp4 时它进入 if 语句。
解决方案:我必须将会话 ID 作为查询字符串传递给页面,然后手动设置它。这对我的用例很有效,因为这个 php 页面不应该 link 到其他页面,将会话 ID 公开为引用 link。不是 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;
试一试(没有die/exit):
<?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);
}
Ilmari 已告诉您情况:请求 mp4 时未设置 $_SESSION[$folder]
。这意味着 iOS 没有发送回 sessionID。
删除 die
将 "fix" 问题,因为代码只是继续,但这是一个转移注意力的问题。它可能会发出一个 "redirect header",但如果你不退出,将会有其他 headers 基本上使重定向请求无效。发出重定向 header.
您需要检查的是是否为这些请求设置了 $_SESSION。您不会在 Apache/NGNIX 访问日志中找到它,但需要自己记录。最简单的情况是将 file_put_contents('\tmp\debug.log\, print_r($_SESSION, true));
添加到代码中。 (将覆盖每个 运行,如果要追加,请使用 fopen)。然后回头看看使用相同的日志记录正在发送(或未发送)哪些 cookie。但是有些东西没有发送 sessionID。
至于解决方案:这很棘手。在正确修复之前,也许您可以使用 IP 地址?不太可靠(事实上,非常不可靠),但如果用户使用特定 IP 登录,那么允许来自该 IP 的任何请求?或者使用您自己的 cookies / session 系统进行实验,看看它们的行为是否相同。暂时能想到的就这些了
来自 Apple 论坛的内容:https://forums.developer.apple.com/thread/60688
Safari seems to be only adding those cookies whose path is different from the request url path. But this seesm to work on other browsers on IOS9 as these may be creating the cookies on the root of the domain.
所以尝试改变请求的路径。