2016-01-15 35 views
6

是否可以爲每個瀏覽器標籤創建會話數?PHP - 每個標籤的會話數

作爲例如用戶打開2個選項卡在他的瀏覽器: 標籤1標籤2

標籤1他有一個會話:

$_SESSION['xxx'] = 'lorem'; 

而且在標籤2會話爲:

$_SESSION['xxx'] = 'ipsum'; 

現在刷新我需要在活動選項卡中獲取當前會話。例如,如果用戶刷新選項卡2,我需要爲負載上的選項卡2獲得$_SESSION['xxx'],該選項是'ipsum'。但$_SESSION['xxx']不應在選項卡1上更改。

是否有任何選項可保存每個選項卡的會話。如果沒有其他選項來處理這個問題?

感謝您的幫助!

+0

按標籤,你的意思是瀏覽器選項卡,對吧? – vitozev

+0

@vitozev是啊:) – lhuber

+0

這是非常相似的這個問題:http://stackoverflow.com/questions/6067009/php-multiple-concurrent-sessions-per-user你可能會在那裏找到你的答案。 –

回答

9

PHP將會話ID存儲在Cookie和Cookie中,而不是每個客戶端(瀏覽器)。所以沒有簡單而簡單的方法來做到這一點。有辦法通過創建自己的會話處理程序來做到這一點,但它們比解決方案更麻煩,因此會帶來自身的風險和複雜性。無論出於何種原因你可能需要這個,我相當確信有比會話分割更好的架構解決方案。

+1

是的,我與它的網址參數:)謝謝你的答案! – lhuber

+0

@Auris,這是一個很好的使用,當你有多個窗口打開。一個有新聞,另一個有Facebook,第三個有你需要登錄的Magnificent Application。使用正常的會話cookie,您可以登錄,然後關閉該選項卡/窗口。但由於其他選項卡/窗口仍然打開,會話仍然活着。您可以重新打開新標籤頁/窗口,無需登錄。我認爲如果應用程序窗口關閉,會話將會消失,從而強制重新登錄。對於正常的會話cookie,直到所有窗口關閉,會話纔會死亡。 – UncaAlby

+0

@UncaAlby嗨,會話實際上當你關閉窗口時就會死掉,它只是在Cookie再次打開時重新使用存儲在cookie中的id重新生成,如果cookie未過期的話。但這不是問題的關鍵。 Ihuber希望在不同的選項卡中爲同一個實體分配兩個會話。這是clinet的功能,在服務器端沒有「乾淨」的方式來做到這一點。在你的例子中,你使用了3個不同的應用這些應用程序擁有自己的會話實體,彼此之間無法訪問(例如,您的超級應用程序無法管理FB會話容器中的變量 - 網絡安全101)。 – Auris

4

我一直在網上搜尋這個問題的答案,還沒有找到一個令人滿意的解決方案。我終於把JavaScript中的某些東西放在一起了。

//generate a random ID, doesn't really matter how  
if(!sessionStorage.tab) { 
    var max = 99999999; 
    var min = 10000000; 
    sessionStorage.tab = Math.floor(Math.random() * (max - min + 1) + min); 
} 

//set tab_id cookie before leaving page 
window.addEventListener('beforeunload', function() { 
    document.cookie = 'tab_id=' + sessionStorage.tab; 
}); 

HTML5 sessionStorage未標籤之間共享的,所以我們可以存儲唯一標籤ID那裏。聆聽窗口上的beforeunload事件告訴我們,我們正在離開(並加載其他頁面)。通過在我們離開之前設置cookie,我們將我們的價值包含在新請求中,而無需任何額外的URL操作。要區分選項卡,您只需在服務器上檢查$_COOKIE['tab_id']並適當存儲會話值。

請注意,Firefox的行爲異常,在觸發window.open()將創建一個共享sessionStorage與其父,給你兩個選項卡具有相同ID的窗口。手動打開一個空白標籤,然後導航到目標URL將爲您提供單獨的存儲空間。到目前爲止,Chrome在我的所有測試中都適用於我。

我意識到這可能不是正確的答案,甚至是一個「好」的答案,但它是的答案。

+0

是的,這可能會起作用,但這又是一次黑客攻擊。如果你正在構建一些個人的東西並且使用它,這很好,但是如果你正在構建一個商業產品並且有人評論你的代碼,那麼很可能你會被簡單地解僱。您在標籤ID下存儲基於應用程序的會話,這意味着在公共計算機上,您的會話可供任何打開該標籤ID的人使用。另外,如果用戶以不同的標籤順序加載不同會話的應用組件,該怎麼辦? - 就像我說的那樣,這適合玩耍,但不能用於合適的解決方案。 – Auris

+0

我認爲你的批評有點不公平,因爲這是一個適當的解決方案的開始:不是將Cookie從會話ID傳遞到網站,而是將Cookie的標籤ID +會話ID傳遞給網站。 – frankster

0

我一直在拍攝一個具有此功能的網絡應用程序。

它還沒有成熟,並有約束和流動,就像必須在URL中傳輸會話ID,如果你的JavaScript發佈到外部的PHP代碼取決於它,但它的功能和適合我的需要(現在)。

我在考慮一個更安全的解決方案,因此請隨時根據您的需求進行調整,並給我您的建議。

<?php 
/** 
* Split $_SESSION by browser Tab emulator. 
* methods exemples are used whith : 
* $session = new SessionSplit(); 
* as SessionSplit may reload the page, it has to be used on top of the code. 
* 
*/ 
class SessionSplit{ 
    public $id; 
    private $gprefix="session_slice_"; 
    private $prefix=""; 
    private $witness=""; 
    function SessionSplit($witness='witness'){ 
     if(session_status()===PHP_SESSION_NONE){ 
      session_start(); 
     } 
     $this->witness=$witness; 
     if($this->get_id()){ 
      $this->prefix=$this->gprefix.$this->id; 
      //set a witness to 'register' the session id 
      $this->set($this->witness,'true'); 
     }else{ 
      // force the session id in the url to not interfere with form validation 
      $actual_link = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; 
      $new_link = $actual_link.(strpos($actual_link,'?')===false?'?':'&'). 
       'session_id='.$this->id; 
      header('Location: '.$new_link); 
     } 
    } 
    private function get_id(){ 
     if(isset($_GET['session_id'])){ 
      $this->id=$_GET['session_id']; 
      return true; 
     }else{ 
      $this->new_id(); 
      return false; 
     } 
    } 
    private function new_id(){ 
     $id=0; 
     while(isset($_SESSION[$this->gprefix.$id.'.'.$this->witness])){$id++;} 
     $this->id=$id; 
    } 
    // ----------- publics 
    public function clearAll(){ 
     foreach($_SESSION as $key=>$value){ 
      if(strpos($key,$this->prefix.'.')===0){ 
       unset($_SESSION[$key]); 
      } 
     } 
    } 
    /** 
    * $is_user=$session->has('user'); 
    * equivalent to 
    * $is_user=isset($_SESSION['user']); 
    * @param {string} $local_id 
    * @return {boolean} 
    */ 
    public function has($local_id){ 
     return isset($_SESSION[$this->prefix.'.'.$local_id]); 
    } 
    /** 
    * 
    * $session->clear('user'); 
    * equivalent to 
    * unset($_SESSION['user']); 
    * @param {string} $local_id 
    */ 
    public function clear($local_id){ 
     unset($_SESSION[$this->prefix.'.'.$local_id]); 
    } 
    /** 
    * $user=$session->get('user'); 
    * equivalent to 
    * $user=$_SESSION['user']; 
    * @param {string} $local_id 
    * @return {mixed} 
    */ 
    public function get($local_id){ 
     if (isset($_SESSION[$this->prefix.'.'.$local_id])) { 
      return $_SESSION[$this->prefix.'.'.$local_id]; 
     }else return null; 
    } 
    /** 
    * $session->set('user',$user); 
    * equivalent to 
    * $_SESSION['user']=$user; 
    * @param {string} $local_id 
    * @param {mixed} $value 
    */ 
    public function set($local_id,$value){ 
     $_SESSION[$this->prefix.'.'.$local_id]=$value; 
    } 
}; 
?>