用户的PHP多个并发会话

17

我正在使用Apache上的PHP开发Web应用程序。 $_SESSION变量被广泛用于需要在多个页面之间保持信息的情况。

我们需要每个用户能够打开多个并发会话,无论他们选择使用哪种浏览器打开新标签或新窗口。目前,当用户打开新标签或新窗口并进入网站时,现有会话将被采用。我该如何防止这种情况发生,以便用户必须(或可以)登录并开始一个新会话,而不会干扰他们已经打开的任何现有会话?

我们的临时解决方法是使用多个浏览器(IE和FF),但显然这不是一个非常理想的做法。


不可能的。您需要编写自己的会话处理脚本,并将其附加到每个URL中。 - user747970
5
每个URL后面都附加“pass if through”,可能会出现什么问题? - a coder
5个回答

10

您描述的行为与浏览器会话的概念相反。为什么用户需要多个会话?这是因为需要强制执行用户访问控制吗?如果是这样,请将用户分配到逻辑组并授予特定组的权限。用户是否需要代表其他用户执行某些操作?如果是这样,请设计网站以围绕该概念进行,而不是尝试为单个用户创建多个会话。

如果您真的必须这样做,可以像在页面之间传递查询参数 (非常不安全!) 那样让其充当一个会话 ID,绕过实际的 $_SESSION,并管理自己的会话概念。再次强调,这不是正常的操作方式,未来只会带来头疼和安全问题。


3
我们有这个需求的原因是由于应用程序的使用方式。例如,销售人员可能需要在任何给定时间打开多个订单输入屏幕。这可能是因为一个客户需要出于各种原因暂时移交给另一名员工。然后,销售人员需要能够为队列中的下一个人开始新订单,而不会干扰已经打开的订单,当原始客户被移交回来时,该订单将完成。在旧系统中,这是通过打开应用程序的多个副本(非基于Web)来完成的。 - John Gardeniers
16
啊,我现在明白了。 :) 你可以改变网站的工作方式,不要将销售代表当前订单存储在会话中。相反,你可以采用更具REST特性的方法[http://www.xml.com/pub/a/2004/08/11/rest.html],其中销售代表正在更新的订单ID是网页URL的一部分。这样,他们就可以打开两个选项卡/窗口并修改两个订单,而会话将完全退出视线。 - Dave
2
接受上述评论的答案,而不是答案本身。 - John Gardeniers

2

非原子并发会话管理可以通过以下伪代码逻辑进行模拟:

function main(){
  $locker = new SessionLocking();
  /** read elements the $_SESSION "cached" copy. **/
  $var1 = $_SESSION['var1'];
  $var2 = $_SESSION['var2'];
  /** Pseudo Atomic Read **/
  $locker->lock(); //session is locked against concurrent access.
  $var3 = $_SESSION['var3'];
  $locker->unlock(); //session is committed to disk (or other) and can be accessed by another script.
  /** Psuedo Atomic Write **/
  $locker->lock(); //session is locked against concurrent access.
  $_SESSION['var4'] = "Some new value";
  $locker->unlock(); //session is committed to disk (or other) and can be accessed by another script
}

CLASS SessionLocking {

private static $lockCounter=0;
private static $isLoaded=false;

function __constructor(){
  if (!self::$isLoaded) load();
}

private function load(){
 $this->lock();
 $this->unlock();
}

private function lock(){
  if ($lockCounter<1) try {session_start();} Catch(){}
  $lockCounter++; 
}

private function unlock(){
  if ($lockCount<1) return;
  $lockCounter--;
  if ($lockCounter<1) try {session_write_close();} Catch(){}
}
}

1

如果可能的话,这将非常困难。

会话不应该担心它们在哪个选项卡中。

此外,如果选项卡1中的会话1打开一个新窗口,会发生什么?它是一个新会话吗?


这是我能找到的关于此事的最佳文献:http://www.php.net/manual/en/ref.session.php#74557 - onteria_
@onteria_ 这似乎很容易被滥用:因此,每个链接、表单、header()和Javascript代码都将把SESSION_NAME值转发到下一个脚本,它将知道必须使用哪个会话。 - a coder

0

虽然回答已经很晚了...

作为一名开发者,我通常需要同时测试不同用户类型(管理员、注册用户、访客等)的界面。Firefox浏览器有一个“多账户容器”插件,可以将cookie按容器分离,每个容器内可以创建多个选项卡。每组选项卡共享cookie,但不跨容器。浏览器将使用不同独立的“PHPSESSID”(或您命名的cookie),因此能够处理多个同时会话。

还有其他扩展和注意事项,例如特殊书签等,但它们超出了本问题的范围。


-3
这是一种方法:
-首先在php.ini中禁用会话cookie:
session.use_cookies = 0

这可以确保不使用cookie传递会话ID。

-然后,请确保在生成所有URL时包含会话ID(您可以通过session_id()函数获取它,例如:

print "<a href= \"http://www.example.com/".session_id()."&showlist=1\">show list</a>";

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接