2013-02-24 67 views
0

我已经使用这个article构建了这个会话类。我确信我遵循了所有的规则和给出的所有信息,但是我的代码不起作用。PHP会话类不起作用

会话类:session.php文件

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) { 

     // Make sure the session cookie is not accessable via javascript 
     $httponly = true; 

     // Hash algorith to use for the session_id 
     $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, nut URL variables 
     ini_set('session.use_only_cookies', 1); 

     // Get session cookie parameters 
     $cookieParams = session_get_cookie_params(); 

     // Set the parameters 
     session_set_cookie_params(
      $cookieParams['lifetime'], 
      $cookieParams['path'], 
      $cookieParams['domain'], 
      $secure, 
      $httponly 
     ); 

     // Change the sesion name 
     session_name($session_name); 

     // 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);  

    } 

    function open() { 

     // Define Connection variables 
     $host = ''; 
     $user = ''; 
     $pass = ''; 
     $dbnm = ''; 

     // Connection string based on connection variables 
     $PDO = new PDO("mysql:host=$host;dbname=$dbnm", $user, $pass); 

     // Connect to DB based on connection string 
     $this->db = $PDO; 
     return true; 

    } 

    function close() { 

     // Close DB connection 
     $this->db->close(); 
     return true; 

    } 

    function read($id) { 

     // If not the read statement is defined 
     if(!isset($this->read_stmt)) { 

      // Prepared statement for getting data from DB 
      $this->read_stmt = $this->db->prepare("SELECT data FROM sessions WHERE id = ? LIMIT 1"); 

     } 

     $this->read_stmt->bind_param('s', $id); // Replace ? with $id 
     $this->read_stmt->execute();    // Execute the prepared statement 
     $this->read_stmt->store_result();   // We store the data returned 
     $this->read_stmt->bind_result($data);  // We bind the result to a $data variable 
     $this->read_stmt->fetch();     // And fetch returned data 

     // This function is defined later 
     // but returns the session key based on the $id 
     $key = $this->getkey($id); 

     // Both the variabels are decrypted and assigned to $data 
     $data = $this->decrypt($data, $key); 

     // We return the results 
     return $data; 

    } 

    function write($id, $data) { 

     // Get unique session key 
     $key = $this->getkey($id); 

     //Encrypt the data 
     $data = $this->encrypt($data); 

     // Assign current time to $time variable 
     $time = time(); 

     // If not the write statement is defined 
     if(!isset($this->write_stmt)) { 

      // Prepared statement for replacing data in DB 
      $this->write_stmt = $this->db->prepare("REPLACE INTO sessions (id, set_time, data, session_key) VALUES (?, ?, ?, ?)"); 

     } 

     $this->write_stmt->bind_param('siss', $id, $time, $data, $key); // Replace ?, ?, ?, ? with $id, $time, $data, $key 
     $this->write_stmt->execute();          // Execute the prepared statement 

     // Return confirmation 
     return true; 

    } 

    function destroy($id) { 

     // If not the delete statement is defined 
     if(!isset($this->delete_stmt)) { 

      // Prepared statement for deleting session data from DB 
      $this->delete_stmt = $this->db->prepare("DELETE FROM sessions WHERE id = ?"); 

     } 

     $this->delete_stmt->bind_param('s', $id); // Replace ? with $id 
     $this->delete_stmt->execute();    // Execute the prepared statement 

     // Return confirmation 
     return true; 

    } 

    function gc($max) { 

     // This function 'Garbage Collector' is emptying the DB for old sessions 
     // this way, the DB takes care of itself. 

     // If not the GC statement is defined 
     if(!isset($this->gc_stmt)) { 

      // Prepared statement for deleting session data from DB 
      $this->gc_stmt = $this->db->prepare("DELETE FROM sessions WHERE set_time < ?"); 

     } 

     // Define $old to be an old statement 
     $old = time() - $max; 

     $this->gc_stmt->bind_param('s', $old); // Replace ? with $old 
     $this->gc_stmt->execute();    // Execute the prepared statement 

     // Return confirmation 
     return true; 

    } 

    private function getkey($id) { 

     // This function is used to get the unique key for encryption from the sessions table. 
     // If there is no session it just returns a new random key for encryption. 

     // If not the select statement is defined 
     if(!isset($this->key_stmt)) { 

      // Prepared statement for selecting session key from DB 
      $this->key_stmt = $this->db->prepare("SELECT session_key FROM sessions WHERE id = ? LIMIT 1"); 

     } 

     $this->key_stmt->bind_param('s', $id); // Replace ? with $old 
     $this->key_stmt->execute();   // Execute the prepared statement 
     $this->key_stmt->store_result();  // We store the data returned 

     // If the select statement returns a row 
     if($this->key_stmt->num_rows == 1) { 

      $this->key_stmt->bind_result($key); // We bind the result to a $data variable 
      $this->read_stmt->fetch();    // And fetch returned data 

      // Then we return the result 
      return $key; 

     } else { 

      // We generate a random key 
      $random_key = hash('sha512', uniqid(mt_rand(1, mt_getrandmax()), true)); 

      // Then we return the result 
      return $random_key; 

     } 

    } 

    private function encrypt($data, $key) { 

     // A complete random key for encryption 
     $salt = 'cH!swe!retReGu7W6bEDRup7usuDUh9THeD2CHeGE*[email protected]@pH'; 

     // We assign a hash encoded version of the random key and session key to the $key 
     $key = substr(hash('sha256', $salt.$key.$salt), 0, 32); 

     // Open module, and create IV 
     $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); 
     $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 

     // Do the encryption and assign it to $encrypted 
     $encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_ECB, $iv)); 

     // And return the encrypted data 
     return $encrypted; 

    } 

    private function decrypt($data, $key) { 

     // The same key for encryption is used for decrytion (obviously) 
     $salt = 'cH!swe!retReGu7W6bEDRup7usuDUh9THeD2CHeGE*[email protected]@pH'; 

     // We assign a hash encoded version of the random key and session key to the $key 
     $key = substr(hash('sha256', $salt.$key.$salt), 0, 32); 

     // Open module, and create IV 
     $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); 
     $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 

     // Do the decryption and assign it to $decrypted 
     $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($data), MCRYPT_MODE_ECB, $iv); 

     // And return the decrypted data 
     return $decrypted; 

    } 

} 

然后我有一个测试两页。我也相信这些网页是正确书写的,所以必须有一些东西阻止工作..我有一个更大的脚本,我使用相同的类,我可以定义新的类$session = new Session();,但是当我开始会话$session->start_session('test', false);脚本死亡。

测试页PHP:tester.php

<? 
require_once('session.php'); 
$session = new Session(); 

$session->start_session('test', false); 

$_SESSION['dims'] = 'This is a session variable'; 

?> 

<a href="tester2.php">click here</a> 

测试第2页PHP:tester2.php

<? 
require_once('session.php'); 
$session = new Session(); 

$session->start_session('test', false); 

echo $_SESSION['dims']; 

?> 

我发现了一个错误500内部服务器错误出现。

+0

您记录了错误吗? – kirugan 2013-02-24 14:06:44

+0

我试过,但实际上没有错误出现.. – Dimser 2013-02-24 14:07:21

+0

好的500错误意味着服务器错误,如果你的服务器不常见,你打开日志记录(在你的代码和服务器配置)比你会看到它。有了明确的错误描述,我们可以帮助更快。 – kirugan 2013-02-24 14:09:33

回答

1

您的班级通过PDO建立了连接,但您所遵循的教程使用MySQLi准备的语句。这两个API不兼容。在PDO等效代码是这样:

 // If not the read statement is defined 
    if(!isset($this->read_stmt)) { 

     // Prepared statement for getting data from DB 
     // Prepare using the named parameter :id instead of ? (though ? can be used in PDO too) 
     $this->read_stmt = $this->db->prepare("SELECT data FROM sessions WHERE id = :id LIMIT 1"); 

    } 
    // If the statement was successfully prepared... 
    if ($this->read_stmt) { 
     // One of 2 param binding methods in PDO... 
     $this->read_stmt->bindParam(':id', $id, PDO::PARAM_STR); 
     $this->read_stmt->execute(); 
     // No correlate for store_result() in PDO... 

     // Fetch the first row and get the data key from it 
     // You don't need to do a bind result in PDO. Instead just fetch() or fetchAll() 
     // more like the old mysql_fetch_*() functions. 
     $row = $this->read_stmt->fetch(PDO::FETCH_ASSOC); 
     $data = $row['data'] 

     // Do the rest of your stuff with data. 
    } 

我就不翻译了上面的整个代码块,但这应该让你开始。 PDO docs on bindParam()有足够的例子,你应该能够找出你的其他查询。

最后,我推荐PDO Tutorial for MySQL Developers,它有很好的例子,但它并不直接解决MySQLi准备语句翻译成PDO语句的问题。