0

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

会话类: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*ewr4n39=E@rAsp7c-Ph@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*ewr4n39=E@rAsp7c-Ph@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 internal server error。

4

1 回答 1

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 文档上bindParam()有足够的示例,您也应该能够找出其他查询。

最后,我推荐MySQL 开发人员的 PDO 教程,它有很好的示例,尽管它没有直接解决将 MySQLi 准备好的语句转换为 PDO 语句的问题。

于 2013-02-24T14:20:18.333 回答