PHP - 每个标签的会话

时间:2016-01-15 09:59:13

标签: php session tabs

是否可以按浏览器标签创建会话?

例如,用户在浏览器中打开了2个标签: 标签1 标签2

标签1 中,他有一个会话:

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

标签2 中,会话为:

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

现在刷新我需要在活动标签中获取当前会话。例如,如果用户刷新选项卡2,我需要在加载时获取$_SESSION['xxx']选项卡2,即“ipsum”。但{1}}不应在标签1上更改。

是否有选项可以保存每个标签的会话。如果没有其他选项来处理这个问题?

感谢您的帮助!

5 个答案:

答案 0 :(得分:12)

PHP将会话ID存储在Cookie中,Cookie存储在每个客户端(浏览器)中,而不是制表符。所以没有简单易行的方法。有一些方法可以通过创建自己的会话处理程序来实现这一点,但它们比解决方案更具黑客性,因此具有自己的风险和复杂性。无论出于何种原因,您可能需要这个,我确信有一个比会话拆分更好的架构解决方案。

答案 1 :(得分:6)

我一直在网上搜索这个问题的答案,还没有找到令人满意的解决方案。我终于用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在我的所有测试中都适合我。

我意识到这可能不是正确答案,甚至是“好”答案,但它是 答案。

答案 2 :(得分:0)

我一直在努力制作一个具有此功能的网络应用程序。

它尚未成熟并且有约束和流程,如果您的javascript根据它发布到外部PHP代码,必须在URL中传输会话ID,但它的功能和适合我的需求(现在)

我正在考虑一个更安全的解决方案,因此请随意根据您的需求进行调整,并向我提出您的建议。

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

答案 3 :(得分:0)

这是我的解决方案;我们正在使用它来允许每个客户端打开多个应用程序视图。

POST以获取数据: 'doStuff = getData&model = GTD&sn = 6789&type = random&date = 18-Dec-2018'

然后,控制器从表中获取数据,为设备构建对象,将其存储到会话对象中,并将其存储在变量中。它会生成每个选项卡的guid,以便用户可以将同一工具与UI中的不同视图进行比较。

$ _ session [$ model] [$ sn] [$ type] [$ guid] [$ key];

当然也将GUID发送回数据对象,以便选项卡知道如何稍后重新调用该数据。

当用户要将结果打印到文件(pdf等)时,它将在POST中发送带有相关数据的帖子。

'doStuff = saveFile&model = GTD&sn = 6789&type = random&calDate = 18-Dec-2018&guid = randomKey'

然后,控制器会将其传递到存储以进行检索。

会话类文件示例:

<?php
class Session {
public $fieldKey1;
public $fieldKey2;

public function GetStorage($model, $sn, $type, $guid, $key) {
    return $_SESSION[$model][$sn][$type][$guid][$key];
}

}

?>

控制器文件:

<?php
require_once('session.php'); 
global $session; //from session class file
switch($_POST['doStuff']) {
  case 'saveFile':
     $session->GetStorage($_POST['model'], $_POST['sn'], $_POST['type'], $_POST['guid'], $key);
     break;
}
?>

这使用户可以查看同一数据的多个视图,而不必覆盖每个选项卡上的数据集。如果您不需要每个选项卡那么多的数据粒度,则当然可以简化$ _SESSION变量的键数。

答案 4 :(得分:0)

Firefox和其他浏览器都有一种方法。

作为开发人员,我通常需要同时测试不同用户类型(管理员,注册用户,访问者等)的界面。 Firefox浏览器具有一个“多帐户容器”附加组件,除其他功能外,它还使cookie按容器分开。可以创建所需数量的容器,并在每个容器中打开选项卡。每套包含的选项卡共享cookie,但不能跨容器共享。浏览器将使用不同的独立“ PHPSESSID”(或者您将其命名为Cookie),从而能够处理多个同时进行的会话。

还有其他扩展名和注意事项,例如特殊书签等,但它们不在此处的讨论范围内。

相关问题