Php 会话类未正确跟踪会话id

Php 会话类未正确跟踪会话id,php,session,pdo,Php,Session,Pdo,这是我正在使用的会话类。 在每个页面上重新生成会话id是否是一个好主意,因为这正是我打算做的。 在每个页面上重新生成会话id时,write函数会执行以下操作:0(rowCount())选择0键从插入的getkey函数1中选择。 当(从rowCount()中)1从getkey函数中选择了1个key,从destroy函数中选择了1个destroct时,read函数将正常工作。 有时我会成功选择0个读取数据记录 0 destroy delete records成功地从destroy函数中删除记录,但它

这是我正在使用的会话类。 在每个页面上重新生成会话id是否是一个好主意,因为这正是我打算做的。 在每个页面上重新生成会话id时,write函数会执行以下操作:0(rowCount())选择0键从插入的getkey函数1中选择。 当(从rowCount()中)1从getkey函数中选择了1个key,从destroy函数中选择了1个destroct时,read函数将正常工作。 有时我会成功选择0个读取数据记录 0 destroy delete records成功地从destroy函数中删除记录,但它应该在read函数、getkey函数和destroy函数中进行选择,因为where子句中的id是数据库表中的id。 其他情况下,我将获得1“读取选定项”0“成功选定关键记录”0“删除旧会话id”并插入新会话id(从写入功能),就像1“读取选定项”1“选定关键项”1“销毁”。 通过read函数,where子句的id将是它应该能够选择的id,即db中的id。这与键和删除功能相同。 有时我会尝试插入两个id,因为已经生成了另一个id,但如果在db中将“设置时间”设置为“唯一”,则不会插入,但如果时间不相同(测试转到另一页),我会在db表中使用另一个id的行。有时在正确的行中只是一个错误的id(不是来自写入函数的id)。没有新行,只有不同的id。会话id是db表中的主键。我确实有点问题,比如一次点击鼠标,两次点击,这可能是原因之一。非常感谢您的帮助。 附注:第5.2.16条 情况1读取选定的0键选择0销毁或如果1读取选定的1键1销毁;为那些第123条的人说id。在页面$id=session_id()和echo$id的php部分的末尾,它是;比如说321。然后在信息回荡的页面底部。 选择0个键结果,where子句的id为321。 然后,加密后的数据会被回显。然后0写入选择1写入成功插入。 这正常吗

enter code here

     class session{
 function __construct(){
//set our custom session functions.
session_set_save_handler(array($this,'open'),array($this,'close'),array   ($this,'read'),array($this,'write'),array($this,'destroy'),array($this,'gc'));
//This line prevents unexpected effects when using objects as save handlers.
register_shutdown_function('session_write_close');
 }
 function start_session($session_name,$secure){
  $httponly = true;
 // hash algorithm to use for the session id.(use hash_algos() to get a list of available hashs.)
  $session_hash = 'sha512';
 // check if hash is available
 if(in_array($session_hash,hash_algos())){
 // set the hash function.
  ini_set('session.hash_function',$session_hash);
 }
  // how many bits per character of the hash.
  ini_set('session.hash_bits_per_character',5);
 // force the session to only use cookies, not url variables.
  ini_set('session.use_only_cookies',1);
  //get session cookie parameters
 $cookieParams = session_get_cookie_params();
 $domain = ($_SERVER['HTTP_HOST'] != 'localhost') ? $_SERVER['HTTP_HOST'] : false;
 session_set_cookie_params($cookieParams["lifetime"],$cookieParams["path"],
  //$cookieparams["domain"],$secure,$httponly);
 $domain,$secure,$httponly);
  // change session name
  session_name($session_name);
  session_name('identitysession');
  // now we can start the session
  session_start();
   // this line regenerates the session and delete the old one.
  // it also generates a new encryption key in the database.
 session_regenerate_id(true);
   }

 protected $db = null;


 function open(){
  if(is_null($this->db)){
 $user = 'myuser'; 
 $pass = 'mypassword';
 try{
   $this->db = new PDO( 'mysql:host=127.0.0.1;dbname= mydb',$user,$pass,
   array(
   PDO::ATTR_ERRMODE    =>PDO::ERRMODE_EXCEPTION,
   PDO::ATTR_DEFAULT_FETCH_MODE=> PDO::FETCH_ASSOC,
   PDO::ATTR_EMULATE_PREPARES =>false));
  }catch (PDOException $e){
   echo 'Connection failed:'.$e->getMessage();
   }
  echo 'open open','<br/>';// the echo for testing
  return true;
  }
      else{
    echo 'not open','<br/>';// the echo for testing
    exit();
   }
 }



 function close(){
  $this->db = null;
  echo 'closed closed','<br/>';// the echo for testing
  return true;
 }


 function read($id){
  $timeout = time()-(30*60);
  echo $id,'<br/>';// the echo for testing
 if(!isset($this->read_stmt)){
     try{
     $this->read_stmt = $this->db->prepare("SELECT id,data,set_time FROM mydbtable WHERE id= :id LIMIT 1 ");
     }catch(PDOException $e){
     echo 'Unable to select from database read:'.$e->getMessage();
     }
 }

   if(isset($this->read_stmt)){
  $this->read_stmt->bindParam(':id',$id, PDO::PARAM_STR);   
  $this->read_stmt->execute();
  $row = $this->read_stmt->fetch(PDO::FETCH_ASSOC);
  $idrow = $row['id'];
  echo 'selected id <br/>' . $idrow,'<br/>';// the echo for testing the selected id of db
  $read_count = $this->read_stmt->rowCount();
  echo $read_count. " Read data records selected successfully<br/>";// the echo for testing

       if($read_count > 0 && $row !=''){
         $data =$row['data'];
         $time_past = $row['set_time'];
           if( $time_past < $timeout){
       echo 'nogood time out';//not completed yet
           }
               elseif($time_past > $timeout){
               echo 'read getting data','<br/>';// the echo for testing
               $key = $this->getkey($id);
               echo 'selected id for key <br/>' . $id,'<br/>';// the echo for testing
               $data = $this->decrypt($data, $key);
               echo 'Data','<br/>';// the echo for testing
               echo $data,'<br/>';// the echo for testing
               return $data;
               }
    }   
        elseif($read_count < 1 && $row ==''){
        return '';
        } 
   } 
 }


  function write($id, $data){   
    $key = $this->getkey($id);
    $data = $this->encrypt($data, $key);
    $time = time();
        if(!isset($this->w_stmt)){
        try{
    $this->w_stmt = $this->db->prepare("SELECT data FROM mydbtable WHERE id= :id LIMIT 1 ");
        }catch(PDOException $e){
        echo 'Unable to select from database:'.$e->getMessage();
        }
        }

  if(isset($this->w_stmt)){
   try{
   $this->w_stmt->execute(array(':id'=>$id));
       $row = $this->w_stmt->fetch(PDO::FETCH_ASSOC);
       }catch(PDOException $e){
       echo 'Unable something from database:'.$e->getMessage();
       }    
       $w_count = $this->w_stmt->rowCount(); 
       echo $w_count. "W stmt records selected successfully";// the echo for testing

   if($w_count > 0 && $row !=''){
   try{
    $this->w_stmt =$this->db->prepare("UPDATE mydbtable SET id = :id, 
   set_time = :time,data = :data, session_key = :session_key");
    $this->w_stmt->execute(array(':id'=>$id,':time'=>$time,':data'=>$data,
   ':session_key'=>$key));
   $wri_count = $this->w_stmt->rowCount(); 
   echo $wri_count. "records updated successfully";// the echo for testing
   }catch (PDOException $e){
  echo 'Can not update  the database:'.$e->getMessage();// the echo for testing
   }      
   }
       elseif($w_count < 1 && $row == ''){
            try{
    $this->w_stmt =$this->db->prepare("INSERT INTO mydbtable (id,set_time,data,session_key)
            VALUES(:id,:time,:data,:session_key)");
            $this->w_stmt->execute(array(':id'=>$id,':time'=>$time,':data'=>$data,
    ':session_key'=>$key));
            $write_count = $this->w_stmt->rowCount();    
            echo $write_count. "w stmt records inserted successfully<br/>";// the echo for testing
            echo $id;
        }catch (PDOException $e){
            echo 'Can not insert the database:'.$e->getMessage();
           }   
         }
  }// if  set 
   }


   function destroy($id){
     echo $id,'<br/>';// the echo for testing
           if(!isset($this->delete_stmt)){
       try{
           $this->delete_stmt = $this->db->prepare("DELETE FROM mydbtable WHERE id = :id");
          }catch(PDOException $e){
          echo 'Unable to delete from database:'.$e->getMessage();
          }
      }

   if(isset($this->delete_stmt)) {
   $this->delete_stmt->bindValue(':id',$id,PDO::PARAM_STR);  
   $this->delete_stmt->execute();
   $delete_count = $this->delete_stmt->rowCount();
   echo $delete_count . " destroy delete records successfully<br/>";// the echo for testing
   echo 'delete ','<br/>';// the echo for testing
   return true;
   } 
   }


    function gc($max){
        if(!isset($this->gc_stmt)){
    try{
        $this->gc_stmt = $this->db->prepare("DELETE FROM mydbtable WHERE set_time < :set_time");
        }catch(PDOException $e){
        echo 'Unable to delete from database:'.$e->getMessage();
        }
        }

   if(isset($this->gc_stmt)){
    $old = time() - $max;
    $this->gc_stmt->execute(array(':set_time'=>$old));
    $gc_count = $this->gc_stmt->rowCount();
    echo $gc_count. " gc records  successfully";// the echo for testing
   }
  return true;
  }


  private function getkey($id){
   echo $id,'<br/>';// the echo for testing
       if(!isset($this->key_stmt)){
    try{
        $this->key_stmt = $this->db->prepare("SELECT session_key FROM mydbtable WHERE id = :id limit 1");
        }catch(PDOException $e){
        echo 'Unable to select from database for key:'.$e->getMessage();
        } 
        }

    if(isset($this->key_stmt)){
    $this->key_stmt->execute(array(':id'=>$id));
    $row = $this->key_stmt->fetch(PDO::FETCH_ASSOC);
    $key_count = $this->key_stmt->rowCount();
    echo $key_count. " key records selected successfully<br/>";

      if($key_count > 0 && $row !=''){
              echo 'key getting key','<br/>';// the echo for testing
              $key = $row['session_key'];
              return $key;
      }
              elseif($key_count < 1 && $row == ''){
          $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));
    echo 'encrypted','<br/>';// the echo for testing
    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);
    echo 'decript','<br/>';// the echo for testing
   return $decrypted;
  }
在此处输入代码
课堂{
函数_u构造(){
//设置自定义会话函数。
会话设置保存处理程序(数组($this,'open')、数组($this,'close')、数组($this,'read')、数组($this,'write')、数组($this,'destroy')、数组($this,'gc'));
//当使用对象作为保存处理程序时,此行可防止出现意外效果。
寄存器关闭功能(“会话写入关闭”);
}
函数启动会话($session\u name,$secure){
$httponly=true;
//用于会话id的哈希算法。(使用hash_algos()获取可用哈希的列表。)
$session_hash='sha512';
//检查哈希是否可用
if(在数组($session\u hash,hash\u algos())中){
//设置哈希函数。
ini_集('session.hash_函数',$session_hash);
}
//哈希的每个字符有多少位。
ini_集('session.hash_bits_per_character',5);
//强制会话仅使用cookie,而不使用url变量。
ini\u集('会话。仅使用\u cookies',1);
//获取会话cookie参数
$cookieParams=会话获取cookie参数();
$domain=($\u服务器['HTTP\u主机]!='localhost')?$\u服务器['HTTP\u主机]:false;
会话设置cookie参数($cookieParams[“lifetime”],$cookieParams[“path”],
//$cookieparams[“域”],$secure,$httponly);
$domain、$secure、$httponly);
//更改会话名称
会话名称($session\u name);
会话名称(“identitysession”);
//现在我们可以开始会话了
会话_start();
//此行将重新生成会话并删除旧会话。
//它还会在数据库中生成一个新的加密密钥。
会话\u重新生成\u id(true);
}
受保护的$db=null;
函数open(){
如果(为空($this->db)){
$user='myuser';
$pass='mypassword';
试一试{
$this->db=newpdo('mysql:host=127.0.0.1;dbname=mydb',$user,$pass,
排列(
PDO::ATTR_ERRMODE=>PDO::ERRMODE_异常,
PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES=>false));
}捕获(PDO$e){
回显“连接失败:”。$e->getMessage();
}
echo“open open”,“
”;//用于测试的echo 返回true; } 否则{ 回显“未打开”,“
;”//用于测试的回显 退出(); } } 函数关闭(){ $this->db=null; echo“closed closed”,“
;”//用于测试的echo 返回true; } 函数读取($id){ $timeout=time()-(30*60); echo$id,
;//用于测试的echo 如果(!isset($this->read stmt)){ 试一试{ $this->read_stmt=$this->db->prepare(“从mydbtable中选择id、数据、设置时间,其中id=:id限制1”); }捕获(PDO$e){ echo“无法从数据库中选择读取:”。$e->getMessage(); } } 如果(设置($this->read_stmt)){ $this->read_stmt->bindParam(':id',$id,PDO::PARAM_STR); $this->read_stmt->execute(); $row=$this->read\u stmt->fetch(PDO::fetch\u ASSOC); $idrow=$row['id']; echo“selected id
”。$idrow,
;//用于测试db的所选id的echo $read\u count=$this->read\u stmt->rowCount(); echo$read_count.“已成功选择读取数据记录”
;//用于测试的echo 如果($read_count>0&&$row!=''){ $data=$row['data']; $time_pass=$row['set_time']; 如果($time_pass<$timeout){ echo'nogood timeout';//尚未完成 } elseif($time\u pass>$timeout){ echo“读取获取数据”,“
”;//用于测试的echo $key=$this->getkey($id); echo“为键
选择的id”。$id,
;//用于测试的echo $data=$this->decrypt($data,$key); 回显“数据”,“
”;//用于测试的回显 echo$data,
;//用于测试的echo 返回$data; } } elseif($read_count<1&&$row=''){ 返回“”; } } } F