2016-09-16 65 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); 
} 
相關問題