2016-01-15 6 views
6

Можно ли делать сеансы на вкладках браузера?PHP - сеанс за вкладку

В качестве примера пользователь открыл 2 вкладки в своем браузере: Tab 1 и Tab 2

В Tab 1 он сеанс:

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

И в Tab 2 сессия:

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

Теперь при обновлении мне нужно получить текущую сессию на активной вкладке. Например, если пользователь обновляет вкладку 2, мне нужно получить $_SESSION['xxx'] для вкладки 2 при загрузке, которая является «ipsum». Но $_SESSION['xxx'] не следует изменять на вкладке 1.

Можно ли сохранить сеансы на вкладку. Если нет других вариантов решения этой проблемы?

Спасибо за помощь!

+0

По вкладке вы подразумеваете вкладку браузера, не так ли? – vitozev

+0

@vitozev yeah :) – lhuber

+0

Это очень похоже на этот вопрос: http://stackoverflow.com/questions/6067009/php-multiple-concurrent-sessions-per-user Здесь вы можете найти свой ответ. –

ответ

9

PHP хранит идентификаторы сеансов в куки и файлы cookie для каждого клиента (браузера), а не для вкладок. Таким образом, нет простого и простого способа сделать это. Есть способы сделать это, создав свои собственные обработчики сеансов, но они больше хаки, чем решения, и, как таковые, имеют свои собственные риски и сложность. По какой-то причине вам может понадобиться это, я совершенно уверен, что есть лучшее архитектурное решение, чем сеансное расщепление.

+1

yep i сделал это с параметрами url :) спасибо за ваш ответ! – lhuber

+0

@Auris, очень хорошее использование для этого, когда у вас открыто несколько окон. У одного есть новости, у другого есть Facebook, а у третьего есть ваше Великолепное приложение, для которого требуется логин. С помощью обычных файлов cookie сеанса вы можете войти в систему, а затем закрыть эту вкладку/окно. Но поскольку другие вкладки/окна все еще открыты, сеанс остается «Живым». Вы можете повторно открыть новую вкладку/окно и не нуждаться в логине. Я думаю, было бы лучше, если окно приложения закрывается, сеанс умирает, тем самым заставляя новый логин. При использовании обычных файлов cookie сеанса сеанс не умирает, пока все окна не будут закрыты. – UncaAlby

+0

@UncaAlby Привет, сеанс фактически умирает при закрытии окна, он просто перестраивается с использованием идентификатора, сохраненного в файле cookie, после его повторного открытия, если cookie не истек. Однако это не вопрос. Ihuber хотел иметь 2 отдельных сеанса для одного и того же объекта на разных вкладках. Это функциональность клиники, и нет «чистого» способа сделать это на стороне сервера. В вашем примере вы использовали 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 не разделяется между вкладками, так что мы можем сохранить уникальный идентификатор вкладки там. Прослушивание события beforeunload в окне говорит нам, что мы уходим (и загружаем другую страницу). Установив файл cookie, прежде чем мы уйдем, мы добавим наше значение в новый запрос без дополнительной обработки URL-адресов. Чтобы различать вкладки, вам просто нужно проверить $_COOKIE['tab_id'] на сервере и сохранить значения сеансов соответствующим образом.

Обратите внимание, что Firefox ведет себя странно, в этом запуске window.open() создаст окно, в котором будет размещено sessionStorage со своим родителем, что даст вам две вкладки с тем же идентификатором. Ручное открытие пустой вкладки, а затем переход на целевой URL даст вам отдельное хранилище. Chrome работает для меня во всех моих тестах.

Я понимаю, что это, вероятно, неправильный ответ или даже «хороший» ответ, но это a ответ.

+0

Да, это может сработать, но опять же, это взломать. Если вы строите что-то личное и используете это, все в порядке, но если вы строите коммерческий продукт propper, а кто-то просматривает ваш код, скорее всего, вас просто уволят за это. Вы храните сеансы на основе приложений под значком вкладки, что означает, что на общедоступном компьютере ваши сеансы доступны для всех, открывающих этот идентификатор. Кроме того, что, если пользователь загружает компоненты приложения с разными сеансами в другом порядке вкладок? - Как я уже сказал, это хорошо для того, чтобы играть, но не может быть использовано в решении для пропеллера. – Auris

+0

Я думаю, что ваша критика немного несправедлива, так как это начало правильного решения: вместо передачи идентификатора сеанса из файла cookie на веб-сайт вы должны передать идентификатор id + id сеанса из файла cookie на веб-сайт. – frankster

0

Я сделал снимок, чтобы сделать веб-приложение с этой функцией.

Он не был созрел и имеет ограничения и потоки, например, должен передавать идентификатор сеанса в URL-адресе, если ваш 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; 
    } 
}; 
?> 
Смежные вопросы