Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 更新另一个用户';s课程-最佳实践?_Php_Codeigniter - Fatal编程技术网

Php 更新另一个用户';s课程-最佳实践?

Php 更新另一个用户';s课程-最佳实践?,php,codeigniter,Php,Codeigniter,与许多web应用程序一样,当我的用户登录到我的站点时,我设置了几个会话变量来控制访问站点功能的权限 每当用户执行会导致这些权限发生更改的操作时,我都会将会话变量作为正常处理流程的一部分进行更新 但有时用户的会话需要根据其他用户的操作进行更新。例如,版主升级用户的权限。主持人无权访问用户的会话空间,因此无法为受影响的用户运行正常的更新功能 我考虑过几种强制更新另一个用户会话的方法,但它们都有缺点: 我可以搜索并删除他们的 会话表中的会话,但 这需要进行完整的表扫描 (其中sessdata类似于“

与许多web应用程序一样,当我的用户登录到我的站点时,我设置了几个会话变量来控制访问站点功能的权限

每当用户执行会导致这些权限发生更改的操作时,我都会将会话变量作为正常处理流程的一部分进行更新

但有时用户的会话需要根据其他用户的操作进行更新。例如,版主升级用户的权限。主持人无权访问用户的会话空间,因此无法为受影响的用户运行正常的更新功能

我考虑过几种强制更新另一个用户会话的方法,但它们都有缺点:

  • 我可以搜索并删除他们的 会话表中的会话,但 这需要进行完整的表扫描 (其中sessdata类似于“%user_id%”), 而且它可能会导致 受影响用户可能需要的内容 从事发电
  • 我可以强制更新会话 周期性地,例如 sess_时间_to_更新被触发。 但这并不能保证 将在用户之前显示 正在尝试访问 更新所针对的功能 需要
  • 我可以运行一系列完整的 每次页面加载时都会更新变量, 但是维持一个 会话是为了避免这种开销
  • 我可以设置一个标志表示需要 对于会话更新,但该信号 必须在每个页面执行时以及在每个控制器中进行询问。(我知道我可以将CI_控制器扩展为我的_控制器,但我不想这样做)
  • 我已经向用户发送了一封电子邮件 通知他们有关变更的信息 允许,而且很容易 让他们单击会话更新链接 (甚至注销并重新登录)。 但不能保证他们是 甚至要阅读超出主题的内容 行,更不用说实际单击 链接
我有什么遗漏吗?我在寻找一颗不存在的魔法子弹吗

(请注意,我已经用CodeIgniter对此进行了标记,并参考了特定于CI的技术细节,因为这就是我正在使用的。也就是说,这不是特定于CI(甚至不是特定于PHP)的问题。)


谢谢你的帮助

一个选项是设置一个“ACL版本”号(针对所有用户或每个用户)。然后在初始化会话时(调用
session\u start()
)检查存储的版本是否与会话的版本匹配。如果没有,请刷新ACL

另一种稍有不同的方法是在sessions表中添加一列(“status”或“dirty”,等等)。然后,不终止会话,只需将该状态更新为
1
。然后在加载会话时,检查该标志是否为1。如果是,请在会话中重新加载缓存数据并将其设置为0。如果没有,请继续

至于更新其他用户的会话,我不会这么做。。。如果会话是由PHP管理的,那么需要终止当前会话并启动要修改的会话。那只是在问问题。。。(您需要这样做,因为PHP的机制不使用序列化。)

至于删除他们的会话,我不会担心完整的表扫描。除非有大量用户一直在更新权限,否则这并不重要。数据丢失是一个重要的问题,因此nicks认为


至于其他两个选项,我想你说得很对,所以我没有其他东西可以提供…

在会话表中添加一列,可以保存用户对象的主键。登录时设置它,稍后使用它更新会话


编辑:如果您不想扩展会话表,请创建一个额外的查找表,其中包含用户对象id和会话密钥链接。

如果您将会话存储为本机php会话,我倾向于不使用它,并允许他们获得某种通知,即需要登录/退出以刷新设置。我也有一些站点,其中会话数据存储在数据库中,然后只在其中写入新设置就更简单了。

我想尝试一下,尽管我的方法并不完全适用于CodeIgniter

我过去解决这个问题的方法是使用构造函数创建一个用户对象模型,该构造函数从存储凭据的数据库主键获取用户ID。我将编写一个静态登录方法,该方法检查登录凭据,然后实例化并返回一个user实例(如果某行的登录正确),然后设置会话

到目前为止还不错,对吧?因此,您的所有权限、访问级别等都存储在数据库中。就像有一个登录方法一样,我们可以有一个刷新方法来重新实例化对象,从数据库中重新获取已经获得的主键

class User{
public function __construct($uid){
  //fetch from the db here
  $sql = 'SELECT FROM User_Table WHERE UserID = ?';
  $params = array($uid);
  //fetch and assign using your flavor of database access, I use PDO
  //set all your object properties for access, as well as user_id, something like 
  //$this->user_id = $result['UserID'];
}

public static function Login($uname, $pass){
  $sql = 'SELECT UserID FROM User WHERE Username = ? AND Password = ?';
  $params = array($uname, md5($pass));
  //again I'm going to employ pseudocode here, fetch according to your preferred system
  if(!empty($result)){
    $_SESSION['user'] = new User($result['UserID']);
  }else{
     //login failed!
     return false;   
  }
}

final public function _refresh(){
  //refresher method.  Since the controller sets all the object properties for access
  //reconstructing and assigning it refreshes these priveliges.
  $_SESSION['user'] = new User($this->user_id);
  }

}
使用此模型,每当我在会话中与用户执行可能需要时间敏感权限的操作时,我都可以在会话中调用用户对象all ready上的refresh。假设我们有一个访问受限表单的控制器函数

function _topSecret(){
$_SESSION['user']->refresh();

if($_SESSION['user']->specific_permission_from_db){
  //Perform the special action, get the view, whatever.
}else{
  //redirect to an error page
}

}
因此,如果您已经为管理员编写了例程,那么他们所需要做的就是在数据库中设置用户的权限,并且当刷新方法在特定的时间敏感函数上运行时,这些数据将被放入用户的会话中。因此,您不一定要更新另一个用户的会话,您只需确定哪些操作是按时间顺序敏感的,它们需要最新的权限,并向会话中的用户对象发出该命令

这对我来说非常有效,因为重构只需要在需要最新权限的操作上执行。再说一次,我不确定它在CI和您的个人应用程序的上下文中有多有用,但我想我可以和大家分享一下。我想你已经读过了