IOS 10 не отправляет идентификатор сеанса при попытке доставить mp4 через X-Sendfile

У меня есть файл PHP, единственная задача которого - проверить, зарегистрирован ли пользователь +, если установлена ​​переменная сеанса, а затем доставляет файл через nginx X-Sendfile. Он отлично работает на любом настольном браузере и ранее в любом мобильном браузере - но не работает ни на одном браузере ios 10 с mp4s. Мне мало смысла в том, что если я прокомментирую строку 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: Если я заменил die() на exit(), тот же эффект. Замена его бессмысленной функцией для уничтожения script также имеет тот же эффект. По какой-то причине он попадает в оператор if, когда я запрашиваю только mp4.

РЕШЕНИЕ: Мне пришлось передать идентификатор сеанса на страницу в виде строки запроса, а затем установить ее вручную. Это хорошо подходит для моего использования, так как эта страница php никогда не должна ссылаться на другие страницы, раскрывая идентификатор сеанса в качестве реферальной ссылки. Не 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;

Ответ 1

Илмари рассказал вам ситуацию: $_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/сеанса, чтобы убедиться, что они ведут себя одинаково. Это все, о чем я могу думать сейчас.


Что-то из форумов Apple: https://forums.developer.apple.com/thread/60688

Safari, кажется, добавляет только те файлы cookie, путь которых отличается от пути URL-адреса запроса. Но этот seem работать с другими браузерами на IOS9, поскольку они могут создавать файлы cookie в корне домена.

Итак, попробуйте изменить путь запроса.

Ответ 2

Попробуйте (без выхода/выхода):

<?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);
}