PHP中的会话类停止工作

时间:2016-04-03 11:39:13

标签: php apache session mysqli php-7

更新: 在迁移到共享主机时,我试图解决这个问题。我在这里找到了会话管理的原始代码 - http://www.wikihow.com/Create-a-Secure-Session-Management-System-in-PHP-and-MySQL

最后我简单地用这个替换了我的课程,然后它开始工作了,尽管如此,我很确定,我没有改变它开始。但后来我开始遇到问题。在家庭服务器上一切正常,但在共享主机上,每个页面显示错误503.如果我刷新了几次,我得到相同的错误如下。出于好奇,我转而使用PHP的原生会话管理......它正常工作。所以我的猜测就是这个问题发生了,因为某些原因导致类无法及时连接到DB。在所有会话类都有一些调用之后。

问题是 - 是否有一种方法可以使用自定义类,但如果失败则能够恢复为原生类?

当准备将我的网站从本地PC移动到托管时,我遇到了一些“子网站”的问题。它具有基于用于在DB中存储会话的公共功能的认证系统。在某些时候(我不确定哪个)它停止了正常工作。

因此,当我输入错误的登录名或密码时,网站会按预期运行,并收到错误消息。由于证明了对数据库的详细信息,因此建立了与数据库的连接。但是当我输入正确的页面时 - 页面刷新就像登录成功一样,但它仍然显示我的登录页面。日志中没有写任何内容。

经过几次尝试和\或刷新后,我确实收到500服务器错误,并在服务器日志中显示以下行:

  

[Sun Apr 03 13:29:42.447631 2016] [:error] [pid 12956:tid 1956] [client 192.168.1.1:60985] PHP警告:session_start():无法解码会话对象。会话已在第141行的C:\ Users \ simbi \ OneDrive \ Documents \!Personal \ projects \ WS \ apache \ htdocs \ genfunc \ functions.php中销毁,引用:cant_post_too_many_links / edocuments / index.php

     

[Sun Apr 03 13:29:42.447631 2016] [:error] [pid 12956:tid 1956] [client 192.168.1.1:60985] PHP警告:session_regenerate_id():无法重新生成会话ID - 会话未激活第144行的C:\ Users \ simbi \ OneDrive \ Documents \!Personal \ projects \ WS \ apache \ htdocs \ genfunc \ functions.php,referer:cant_post_too_many_links / edocuments / index.php

     

[Sun Apr 03 13:29:42.447631 2016] [:error] [pid 12956:tid 1956] [client 192.168.1.1:60985] PHP警告:mysqli :: prepare():无法在C中获取mysqli :\用户\ simbi \ OneDrive \ Documents \!Personal \ projects \ WS \ apache \ htdocs \ genfunc \ functions.php第192行,referer:cant_post_too_many_links / edocuments / index.php

     

[Sun Apr 03 13:29:42.447631 2016] [:error] [pid 12956:tid 1956] [client 192.168.1.1:60985] PHP致命错误:未捕获错误:在null上调用成员函数bind_param()在C:\ Users \ simbi \ OneDrive \ Documents \!Personal \ projects \ WS \ apache \ htdocs \ genfunc \ functions.php:195 \ n堆栈跟踪:\ n#0 C:\ Users \ simbi \ OneDrive \ Documents \! Personal \ projects \ WS \ apache \ htdocs \ genfunc \ globalstart.php(7):session-> gc(1)\ n#1 C:\ Users \ simbi \ OneDrive \ Documents \!Personal \ projects \ WS \ apache \ htdocs \ edocuments \ index.php(2):include_once('C:\\ Users \\ simbi \\ ...')\ n#2 {main} \ n抛出C:\ Users \ simbi \ OneDrive \ Documents \!Personal \ projects \ WS \ apache \ htdocs \ genfunc \ functions.php 195行,referer:cant_post_too_many_links / edocuments / index.php

我想,也许在index.php中包含了一些错误,因为它显示了这样一个截断的路径,但即使改变它也无济于事。

globalstart.php实际上非常小,我在这里看不到问题:

<?php
#include settings
include_once "../genfunc/config.php";
include_once "../genfunc/functions.php";
$session = new session();
$session->start_session('_s', true);
$session->gc(1);
$loggedin = login_check();
?>

显然不喜欢gc(1)。虽然functions.php中的行是$ this-&gt; gc_stmt-&gt; bind_param('s',$ old);在会话类的gc($ max)函数中如下:

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 algorithm to use for the sessionid. (use hash_algos() to get a list of available hashes.)
        $session_hash = 'sha512';
        // Check if hash is available
        if (in_array($session_hash, hash_algos())) {
            // Set the has function.
            ini_set('session.hash_function', $session_hash);
        }
        // How many bits per character of the hash.
        // The possible values are '4' (0-9, a-f), '5' (0-9, a-v), and '6' (0-9, a-z, A-Z, "-", ",").
        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(); 
        // Set the parameters
        session_set_cookie_params($cookieParams["lifetime"], $cookieParams["path"], $cookieParams["domain"], $secure, $httponly); 
        // Change the session name 
        session_name($session_name);
        // Now we cat 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() {
        global $sesuser, $sespass, $mhost, $mdbname, $mport, $msocket;
        $mysqli = new mysqli($mhost, $sesuser, $sespass, $mdbname, $mport, $msocket);
        $this->db = $mysqli;
        return true;
    }
    function close() {
        $this->db->close();
        return true;
    }
    function read($id) {
        if(!isset($this->read_stmt)) {
            $this->read_stmt = $this->db->prepare("SELECT data FROM `ed__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;
    }
    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 `ed__sessions` (id, set_time, data, session_key) VALUES (?, ?, ?, ?)");
        }
        $this->w_stmt->bind_param('siss', $id, $time, $data, $key);
        $this->w_stmt->execute();
        return true;
    }
    function destroy($id) {
        if(!isset($this->delete_stmt)) {
            $this->delete_stmt = $this->db->prepare("DELETE FROM `ed__sessions` WHERE id = ?");
        }
        $this->delete_stmt->bind_param('s', $id);
        $this->delete_stmt->execute();
        return true;
    }
    function gc($max) {
        if(!isset($this->gc_stmt)) {
            $this->gc_stmt = $this->db->prepare("DELETE FROM `ed__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 `ed__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 = 'u@cewPpn7e9R9pE2HUe-ebH7=EcC!*7Tw!s4espu@hsWDR3DtDuHrGu6hEAGrrHe';
        $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 = 'u@cewPpn7e9R9pE2HUe-ebH7=EcC!*7Tw!s4espu@hsWDR3DtDuHrGu6hEAGrrHe';
        $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;
    }
}

老实说,我没有看到这里有什么问题,因为这是非常通用的代码,几年前我从其他网站复制过,之前就有用了。但我注意到在数据库中,由于某种原因在登录期间创建了2个会话。也许它失败的原因,但我不明白为什么第二个创建。

有人可以提供建议吗?如果需要,我可以添加与此相关的代码的其他部分。

0 个答案:

没有答案