是否可以按浏览器标签创建会话?
例如,用户在浏览器中打开了2个标签: 标签1 和标签2
在标签1 中,他有一个会话:
$_SESSION['xxx'] = 'lorem';
在标签2 中,会话为:
$_SESSION['xxx'] = 'ipsum';
现在刷新我需要在活动标签中获取当前会话。例如,如果用户刷新选项卡2,我需要在加载时获取$_SESSION['xxx']
选项卡2,即“ipsum”。但{1}}不应在标签1上更改。
是否有选项可以保存每个标签的会话。如果没有其他选项来处理这个问题?
感谢您的帮助!
答案 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),从而能够处理多个同时进行的会话。
还有其他扩展名和注意事项,例如特殊书签等,但它们不在此处的讨论范围内。