0

我在很多地方都没有找到解决这个问题的方法。我完全不知所措,我是修改会话并尝试实现安全会话接口和会话处理程序的新手。我得到的错误是

警告:session_set_save_handler() 期望参数 1 是 SessionHandlerInterface,对象在 C:\wamp\www\SecSessionHandler.php 第 124 行给出。

很抱歉,很长的帖子!

这是两个各自的文件:

SecSession.php:

<?php
class SecSession {
    /**
     * Encryption algorithm
     */
    protected $_algo= MCRYPT_RIJNDAEL_128;
    /**
     * Key for encryption/decryption
    */
    protected $_key;
    /**
     * Key for HMAC authentication
    */
    protected $_auth;
    /**
     * Path of the session file
     */
    protected $_path;
    /**
     * Session name (optional)
     */
    protected $_name;
    /**
     * Size of the IV vector for encryption
     */
    protected $_ivSize;
    /**
     * Cookie variable name of the encryption + auth key
     */
    protected $_keyName;
    /**
     * Generate a random key using openssl
     * fallback to mcrypt_create_iv
     */
    protected function _randomKey($length=128) {
      if(function_exists('openssl_random_pseudo_bytes')) {
        $rnd = openssl_random_pseudo_bytes($length, $strong);
        if ($strong === true) {
          return $rnd;
        }
      }
      return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
    }
    /**
     * Constructor
     */
    public function __construct()
    {

      session_set_save_handler(
        array($this, "open"),
        array($this, "close"),
        array($this, "read"),
        array($this, "write"),
        array($this, "destroy"),
        array($this, "gc")
      );
      if (!extension_loaded('mcrypt')) {
        throw new Exception("The SecureSession class needs the Mcrypt PHP extension, please install it.");
      }
    }
    /**
     * Open the session
     *
     * @param  string $save_path
     * @param  string $session_name
     * @return bool
     */
    public function open($save_path, $session_name)
    {
      $this->_path    = $save_path.'/';
        $this->_name    = $session_name;
        $this->_keyName = "KEY_$session_name";
        $this->_ivSize  = mcrypt_get_iv_size($this->_algo, MCRYPT_MODE_CBC);
        if (empty($_COOKIE[$this->_keyName]) || strpos($_COOKIE[$this->_keyName],':')===false) {
        $keyLength    = mcrypt_get_key_size($this->_algo, MCRYPT_MODE_CBC);
        $this->_key   = self::_randomKey($keyLength);
        $this->_auth  = self::_randomKey(32);
        $cookie_param = session_get_cookie_params();
        setcookie(
          $this->_keyName,
          base64_encode($this->_key) . ':' . base64_encode($this->_auth),
          ($cookie_param['lifetime'] > 0) ? time() + $cookie_param['lifetime'] : 0,
          $cookie_param['path'],
          $cookie_param['domain'],
          $cookie_param['secure'],
          $cookie_param['httponly']
        );
        } else {
        list ($this->_key, $this->_auth) = explode (':',$_COOKIE[$this->_keyName]);
        $this->_key  = base64_decode($this->_key);
        $this->_auth = base64_decode($this->_auth);
      }
        return true;
    }
    /**
     * Close the session
     */
    public function close()
    {
      return true;
    }
    /**
     * Read and decrypt the session
     */
    public function read($id)
    {
      $sess_file = $this->_path.$this->_name."_$id";
      if (!file_exists($sess_file)) {
        return false;
      }
      $data      = file_get_contents($sess_file);
      list($hmac, $iv, $encrypted)= explode(':',$data);
      $iv        = base64_decode($iv);
      $encrypted = base64_decode($encrypted);
      $newHmac   = hash_hmac('sha256', $iv . $this->_algo . $encrypted, $this->_auth);
      if ($hmac !== $newHmac) {
        return false;
      }
      $decrypt = mcrypt_decrypt(
        $this->_algo,
        $this->_key,
        $encrypted,
        MCRYPT_MODE_CBC,
        $iv
      );
      return rtrim($decrypt, "\0");
    }
    /**
     * Encrypt and write the session
     */
    public function write($id, $data)
    {
      $sess_file = $this->_path . $this->_name . "_$id";
        $iv        = mcrypt_create_iv($this->_ivSize, MCRYPT_DEV_URANDOM);
      $encrypted = mcrypt_encrypt(
        $this->_algo,
        $this->_key,
        $data,
        MCRYPT_MODE_CBC,
        $iv
      );
      $hmac  = hash_hmac('sha256', $iv . $this->_algo . $encrypted, $this->_auth);
      $bytes = file_put_contents($sess_file, $hmac . ':' . base64_encode($iv) . ':' . base64_encode($encrypted));
      return ($bytes !== false);
    }
    /**
     * Destroy the session
     */
    public function destroy($id)
    {
      $sess_file = $this->_path . $this->_name . "_$id";
      setcookie ($this->_keyName, '', time() - 3600);
        return(@unlink($sess_file));
    }
    /**
     * Garbage Collector
     */
    public function gc($max)
    {
        foreach (glob($this->_path . $this->_name . '_*') as $filename) {
        if (filemtime($filename) + $max < time()) {
          @unlink($filename);
        }
      }
      return true;
    }
}

SecSessionHandler.php:

<?php

class SecureSessionHandler extends SecSession {

    protected $key, $name, $cookie;

    public function start()
    {
        if (session_id() === '') {
            if (session_start()) {
                return mt_rand(0, 4) === 0 ? $this->refresh() : true; // 1/5
            }
        }

        return false;
    }

    public function forget()
    {
        if (session_id() === '') {
            return false;
        }

        $_SESSION = [];

        setcookie(
            $this->name,
            '',
            time() - 42000,
            $this->cookie['path'],
            $this->cookie['domain'],
            $this->cookie['secure'],
            $this->cookie['httponly']
        );

        return session_destroy();
    }

    public function refresh()
    {
        return session_regenerate_id(true);
    }


    public function isExpired($ttl = 30)
    {
        $last = isset($_SESSION['_last_activity'])
            ? $_SESSION['_last_activity']
            : false;

        if ($last !== false && time() - $last > $ttl * 60) {
            return true;
        }

        $_SESSION['_last_activity'] = time();

        return false;
    }

    public function isFingerprint()
    {
        $hash = md5(
            $_SERVER['HTTP_USER_AGENT'] .
            (ip2long($_SERVER['REMOTE_ADDR']) & ip2long('255.255.0.0'))
        );

        if (isset($_SESSION['_fingerprint'])) {
            return $_SESSION['_fingerprint'] === $hash;
        }

        $_SESSION['_fingerprint'] = $hash;

        return true;
    }

    public function isValid()
    {
        return ! $this->isExpired() && $this->isFingerprint();
    }

    public function get($name)
    {
        $parsed = explode('.', $name);

        $result = $_SESSION;

        while ($parsed) {
            $next = array_shift($parsed);

            if (isset($result[$next])) {
                $result = $result[$next];
            } else {
                return null;
            }
        }

        return $result;
    }

    public function put($name, $value)
    {
        $parsed = explode('.', $name);

        $session =& $_SESSION;

        while (count($parsed) > 1) {
            $next = array_shift($parsed);

            if ( ! isset($session[$next]) || ! is_array($session[$next])) {
                $session[$next] = [];
            }

            $session =& $session[$next];
        }

        $session[array_shift($parsed)] = $value;
    }

}

$session = new SecureSessionHandler();

ini_set('session.save_handler', 'files');
session_set_save_handler($session, false);
session_save_path(__DIR__ . '\sessions');

$session->start();

if ( ! $session->isValid(5)) {
    $session->destroy();
}

$session->put('xxxx', 'xxxxxx');
4

1 回答 1

1

You forgot to tell PHP that your SecSession class implements the interface SessionHandlerInterface. You can do that in this way:

class SecSession implements SessionHandlerInterface {
于 2015-07-17T16:43:46.860 回答