У меня есть файл 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 (), тот же эффект. Замена его бессмысленной функцией для уничтожения скрипта также имеет тот же эффект. По какой-то причине он попадает в оператор 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;
Илмари рассказал вам ситуацию: $_SESSION[$folder]
не устанавливается, когда запрашивается mp4. Это означает, что iOS не отправляет sessionID обратно.
Удаление die
«исправит» проблему, поскольку код просто продолжается, но это красная сельдь. Возможно, выдается «заголовок перенаправления», но если вы не выйдете, будут другие заголовки, которые по существу аннулируют запрос на перенаправление. Всегда иметь выход (или умереть) после выдачи заголовка перенаправления.
Вам нужно проверить, установлен ли $ _SESSION для этих запросов. Вы не найдете этого в журналах доступа Apache / NGNIX, но вам придется регистрировать его самостоятельно. Самый простой случай — это добавить file_put_contents('\tmp\debug.log\, print_r($_SESSION, true));
в код. (Будет перезаписывать каждый прогон, используйте fopen, если вы хотите добавить). Затем вернитесь, чтобы увидеть, какие куки отправляются (или не отправляются) с использованием той же регистрации. Но что-то не отправляет sessionID.
Что касается решения: это сложно. Пока это не исправлено, возможно, вы можете использовать IP-адрес? Не такой надежный (на самом деле, очень ненадежный), но если пользователь вошел в систему с использованием определенного IP-адреса, то разрешить любой запрос с этого IP-адреса? Или поэкспериментируйте с использованием своих собственных файлов cookie / сеансов, чтобы увидеть, ведут ли они себя так же. Это все, что я могу думать сейчас.
Что-то из форумов Apple: https://forums.developer.apple.com/thread/60688
Похоже, что Safari добавляет только те файлы cookie, путь которых отличается от пути URL запроса. Но это похоже на работу в других браузерах на IOS9, так как они могут создавать куки в корне домена.
Поэтому попробуйте изменить путь запроса.
Попробуйте это (без кубика / выхода):
<?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);
}