Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/232.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 使用SessionHandlerInterface与MySQL数据库…请告知_Php_Security - Fatal编程技术网

Php 使用SessionHandlerInterface与MySQL数据库…请告知

Php 使用SessionHandlerInterface与MySQL数据库…请告知,php,security,Php,Security,我已经通过以下方式生成了以下代码 及 这里我使用MySQL数据库来存储和检索会话变量。这段代码运行良好。不过,如果您能指出错误并分享您对这段代码的输入,那就太好了 class MySessionHandler implements SessionHandlerInterface { public function open($savePath, $sessionName) { $host = 'localhost'; $user = '******';

我已经通过以下方式生成了以下代码

这里我使用MySQL数据库来存储和检索会话变量。这段代码运行良好。不过,如果您能指出错误并分享您对这段代码的输入,那就太好了

class MySessionHandler implements SessionHandlerInterface
{

    public function open($savePath, $sessionName)
    { 

   $host = 'localhost';
   $user = '******';
   $pass = '******';
   $name = '*******';
   $mysqli = new mysqli($host, $user, $pass, $name);
   $this->db = $mysqli;
   return true;

    }

    public function close()
    {
        return true;
    }

    public function read($id)
    {
        if(!isset($this->read_stmt)) {
      $this->read_stmt = $this->db->prepare("SELECT data FROM sessions WHERE id = ? LIMIT 1");
   }
   $this->read_stmt->bind_param('s', $id);
   $this->read_stmt->execute();
   $this->read_stmt->store_result();
   $this->read_stmt->bind_result($data);
   $this->read_stmt->fetch();
   $key = $this->getkey($id);
   $data = $this->decrypt($data, $key);
   return $data;
    }

    public function write($id, $data)
    {
         // Get unique key
   $key = $this->getkey($id);
   // Encrypt the data
   $data = $this->encrypt($data, $key);

   $time = time();
   if(!isset($this->w_stmt)) {
      $this->w_stmt = $this->db->prepare("REPLACE INTO sessions (id, set_time, data, session_key) VALUES (?, ?, ?, ?)");
   }

   $this->w_stmt->bind_param('siss', $id, $time, $data, $key);
   $this->w_stmt->execute();
   return true;
    }

    public function destroy($id)
    {
       if(!isset($this->delete_stmt)) {
      $this->delete_stmt = $this->db->prepare("DELETE FROM sessions WHERE id = ?");
   }
   $this->delete_stmt->bind_param('s', $id);
   $this->delete_stmt->execute();
   return true;
    }

    public function gc($maxlifetime)
    {
        if(!isset($this->gc_stmt)) {
      $this->gc_stmt = $this->db->prepare("DELETE FROM sessions WHERE set_time < ?");
   }
   $old = time() - $max;
   $this->gc_stmt->bind_param('s', $old);
   $this->gc_stmt->execute();
   return true;
    }

   private function getkey($id) {
   if(!isset($this->key_stmt)) {
      $this->key_stmt = $this->db->prepare("SELECT session_key FROM sessions WHERE id = ? LIMIT 1");
   }
   $this->key_stmt->bind_param('s', $id);
   $this->key_stmt->execute();
   $this->key_stmt->store_result();
   if($this->key_stmt->num_rows == 1) { 
      $this->key_stmt->bind_result($key);
      $this->key_stmt->fetch();
      return $key;
   } else {
      $random_key = hash('sha512', uniqid(mt_rand(1, mt_getrandmax()), true));
      return $random_key;
   }

}
   private function encrypt($data, $key) {
   $salt = 'cH!swe!retReGu7W6bEDRup7usuDUh9THeD2CHeGE*ewr4n39=E@rAsp7c-Ph@pH';
   $key = substr(hash('sha256', $salt.$key.$salt), 0, 32);
   $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
   $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
   $encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_ECB, $iv));
   return $encrypted;
   }
    private function decrypt($data, $key) {
   $salt = 'cH!swe!retReGu7W6bEDRup7usuDUh9THeD2CHeGE*ewr4n39=E@rAsp7c-Ph@pH';
   $key = substr(hash('sha256', $salt.$key.$salt), 0, 32);
   $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
   $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
   $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($data), MCRYPT_MODE_ECB, $iv);
   return $decrypted;
   }
}

$handler = new MySessionHandler();
session_set_save_handler($handler, true);
session_start();
类MySessionHandler实现SessionHandlerInterface
{
公用函数打开($savePath,$sessionName)
{ 
$host='localhost';
$user='*****';
$pass='*****';
$name='********';
$mysqli=newmysqli($host、$user、$pass、$name);
$this->db=$mysqli;
返回true;
}
公共功能关闭()
{
返回true;
}
公共函数读取($id)
{
如果(!isset($this->read stmt)){
$this->read_stmt=$this->db->prepare(“从id=限制1的会话中选择数据”);
}
$this->read_stmt->bind_param('s',$id);
$this->read_stmt->execute();
$this->read_stmt->store_result();
$this->read\u stmt->bind\u result($data);
$this->read_stmt->fetch();
$key=$this->getkey($id);
$data=$this->decrypt($data,$key);
返回$data;
}
公共函数写入($id$data)
{
//获取唯一密钥
$key=$this->getkey($id);
//加密数据
$data=$this->encrypt($data,$key);
$time=time();
如果(!isset($this->w_stmt)){
$this->w_stmt=$this->db->prepare(“替换为会话(id、设置时间、数据、会话密钥)值(?、、?)”;
}
$this->w_stmt->bind_param('siss',$id,$time,$data,$key);
$this->w_stmt->execute();
返回true;
}
公共功能销毁($id)
{
如果(!isset($this->delete_stmt)){
$this->delete_stmt=$this->db->prepare(“从id=?”的会话中删除”);
}
$this->delete_stmt->bind_param('s',$id);
$this->delete_stmt->execute();
返回true;
}
公共函数gc($maxlifetime)
{
如果(!isset($this->gc_stmt)){
$this->gc\u stmt=$this->db->prepare(“从设置时间的会话中删除”);
}
$old=time()-$max;
$this->gc_stmt->bind_param('s',$old);
$this->gc_stmt->execute();
返回true;
}
私有函数getkey($id){
如果(!isset($this->key stmt)){
$this->key_stmt=$this->db->prepare(“从id=?限制1的会话中选择会话密钥”);
}
$this->key\u stmt->bind\u param('s',$id);
$this->key_stmt->execute();
$this->key\u stmt->store\u result();
如果($this->key\u stmt->num\u rows==1){
$this->key\u stmt->bind\u result($key);
$this->key_stmt->fetch();
返回$key;
}否则{
$random_key=hash('sha512',uniqid(mt_rand(1,mt_getrandmax()),true));
返回$random_键;
}
}
私有函数加密($data,$key){
$salt='cH!swe!retregu7w6bedrup7usudu2hege*ewr4n39=E@rAsp7c-Ph@pH';
$key=substr(散列('sha256',$salt.$key.$salt),0,32);
$iv_size=mcrypt_get_iv_size(mcrypt_RIJNDAEL_256,mcrypt_MODE_ECB);
$iv=mcrypt\u create\u iv($iv\u大小,mcrypt\u兰德);
$encrypted=base64_encode(mcrypt_encrypt(mcrypt_RIJNDAEL_256,$key,$data,mcrypt_MODE_ECB,$iv));
返回$encrypted;
}
私有函数解密($data,$key){
$salt='cH!swe!retregu7w6bedrup7usudu2hege*ewr4n39=E@rAsp7c-Ph@pH';
$key=substr(散列('sha256',$salt.$key.$salt),0,32);
$iv_size=mcrypt_get_iv_size(mcrypt_RIJNDAEL_256,mcrypt_MODE_ECB);
$iv=mcrypt\u create\u iv($iv\u大小,mcrypt\u兰德);
$decrypted=mcrypt_decrypt(mcrypt_RIJNDAEL_256,$key,base64_decode($data),mcrypt_MODE_ECB,$iv);
返回$decrypted;
}
}
$handler=新的MySessionHandler();
会话设置保存处理程序($handler,true);
会话_start();
谢谢你的时间


干杯

您没有锁定会话。这是最大的错误

每当PHP中的请求启动会话并从文件中读取数据时,PHP就会获取该文件的锁,任何并行请求都会停止并等待
session\u start()
函数,直到释放锁为止

如果不锁定,将发生以下情况:第一个请求读取数据库中的所有数据。第二个请求也读取相同的数据。第一个请求将一个值更改为a。第二个请求将另一个值更改为B。第一个请求结束并将其a写回数据库。然后第二个请求用B写回更改,但没有A。数据丢失


我注意到的另一件事是:为什么要用base64对加密数据进行编码?这不是必需的,数据库可以接受二进制数据。这样做的唯一好处是,您的主人可以卖给您一台更大的机器。

谢谢斯文……非常好的投入。我不知道如何在php中锁定。我会更新代码。