• session共享,格式json,php不能简单的设置session.serialize_handler=json,目前只有php,wddx(xml),安装扩展后还有igbinary(二进制)


    即使session_save_handler被自己的类或者方法重写,write与read的出入数据都还是被序列化的,而且被session序列化不是一般的序列化...还是不能解解决memcached保存session数据为json的格式。

    貌似php_memcached扩展有个option是可以选择序列化方式的有json方式的选项,这个还没试过,就怕只有是test|s:4:"data"中右边的部分json编码,再就是自己实现session的过程。。。

    session被重新handler后的执行session_start的顺序:

    在类析构函数里执行session_write_close函数

    open
    read--eke723bndobd24jhtn4sivb1i6
    gc(有一定的概率执行)
    write--eke723bndobd24jhtn4sivb1i6,
    close

    执行:$_SESSON['test']='data';$_SESSION['test2']=2;赋值操作:

    open
    read--eke723bndobd24jhtn4sivb1i6
    ------------------
    write--eke723bndobd24jhtn4sivb1i6,--test|s:4:"data";test2|i:2;
    close
    不管session被赋值几次,都只有一次读取和写入操作。

    执行:echo $_SESSION['test'];echo $_SESSION['test2'];

    open
    read--eke723bndobd24jhtn4sivb1i6
    ------------------
    12 write--eke723bndobd24jhtn4sivb1i6,--test|i:1;test2|i:2;
    close

    读取之后也要最后写入一次。即使没有session写操作。

    附上session_save_handler类:

    class Cache_Session_Handler
    {
        public $_memcache;
       public function __construct()
       {
            $this->_memcache = new Memcache;
            $this->_memcache->addServer(
                    '192.168.11.23', 11211, 1
            );
          session_set_save_handler(
             array($this, "open"),
             array($this, "close"),
             array($this, "read"),
             array($this, "write"),
             array($this, "destroy"),
             array($this, "gc")
          );
        }
    
        public function open()
        {
            echo "open<br/>";
            $this->_lifetime = ini_get('session.gc_maxlifetime');
            return TRUE;
        }
    
        public function read($id)
        {
            echo "read--{$id}<br/>";
            $data = $this->_memcache->get($id);
            return $data;
        }
    
        public function write($id, $data)
        {
            echo "write--{$id},--{$data}<br/>";
            $ttl = 1200;
            //var_dump($data);
            $result = $this->_memcache->replace($id, $data, 0, $ttl);
            if($result === FALSE)
            {
                $result = $this->_memcache->add($id, $data, 0, $ttl);
            }
            return $result;
        }
    
        public function destroy($id)
        {
            echo "destory--{$id}<br/>";
            return $this->_memcache->delete($id);
        }
    
        public function gc()
        {
            echo "gc<br/>";
            return TRUE;
        }
    
        public function close()
        {
            echo "close<br/>";
            return TRUE;
        }
    
        public function __destruct()
        {
            //session_write_close();
        }
    }
    new Cache_Session_Handler();
    session_start();

    自己实现的session的功能,借用session_start产生cookie,也可以手动生成session_id自己控制cookie。

    <?php
    Class Usession
    {
        public static $userdata;
        public static $destruct = true;
        public $memObj;
        public $session_name;
        public $session_id;
        public $sess_match_ip=false;
        public $sess_match_useragent=false;
        public $now;
        public $config_session = array(
            'cookie_prefix'    => "",
            'cookie_domain'    => ".mypharma.com",
            'cookie_path'       => "/",
            'cookie_secure'    => FALSE,
            'cookie_httponly'    => FALSE,
            
            'sess_cookie_name'        => 'mphsess',
            'sess_expiration'            => 0,
            'sess_expire_on_close'    => true,
            'sess_memcached_ttl'      => 864000,
            'sess_match_ip'            => TRUE,
            'sess_match_useragent'    => TRUE,
        );
        
        private static $_instance;
        
        protected $_memcache_conf    = array(
            'default' => array(
                'default_host'        => '127.0.0.1',
                'default_port'        => 11211,
                'default_weight'    => 1
            )
        );
        
        public static function getInstance($params = array())
        {
            if(! (self::$_instance instanceof self) )   
            {    
                self::$_instance = new self($params);    
            }  
            return self::$_instance;
        }
        
        private function __clone()  
        {  
        }
        
        private function __construct($params = array())
        {
            include_once __DIR__."/config_memcached.php";
            $this->set_config($config_session,$_memcache_conf);
            $this->now = time();
            $this->mem_create();
            $this->session_name = $config_session['sess_cookie_name'].'_id';
            $this->session_id = isset($_COOKIE[$this->session_name]) ? $_COOKIE[$this->session_name] : null;
            if(empty($params)){
                $this->sess_create();
            }
        }
        
        public function set_config($config_session,$_memcache_conf)
        {
            if(!empty($config_session) AND is_array($config_session))
            {
                foreach($config_session as $k => $v){
                    $this->config_session[$k] = $v;
                }
            }
            if(!empty($_memcache_conf) AND is_array($_memcache_conf))
            {
                $this->_memcache_conf = null;
                foreach($_memcache_conf as $k => $v){
                    $this->_memcache_conf[$k] = $v;
                }
            }
        }
        
        public function set_session_id($session_id)
        {
            $this->session_id = $session_id;
            //$this->set_session_cookie(true,true);
        }
        
        public function sess_check()
        {
            // Is the session data we unserialized an array with the correct format?
            if ( ! is_array(self::$userdata) OR ! isset(self::$userdata['session_id']) OR ! isset(self::$userdata['ip_address']) OR ! isset(self::$userdata['user_agent']) OR ! isset(self::$userdata['last_activity']))
            {
                $this->sess_destroy();
                return FALSE;
            }
    
            // Does the IP Match?
            if ($this->sess_match_ip == TRUE AND self::$userdata['ip_address'] != $this->ip_address())
            {
                $this->sess_destroy();
                return FALSE;
            }
    
            // Does the User Agent Match?
            if ($this->sess_match_useragent == TRUE AND trim(self::$userdata['user_agent']) != trim(substr($this->user_agent(), 0, 120)))
            {
                $this->sess_destroy();
                return FALSE;
            }
    
            return TRUE;
        }
        
        public function set_session_cookie($flag=true,$isset=false)
        {
            $secure = (bool) $this->config_session['cookie_secure'];
            $http_only = (bool) $this->config_session['cookie_httponly'];
    
            if ($this->config_session['sess_expiration'] !== FALSE)
            {
                $expire = ($this->config_session['sess_expire_on_close'] == true) ? 0 : $this->config_session['sess_expiration']+time();
            }
    
            if ($this->config_session['cookie_path'])
            {
                $path = $this->config_session['cookie_path'];
            }
    
            if ($this->config_session['cookie_domain'])
            {
                $domain = $this->config_session['cookie_domain'];
            }
            $cookieA = array(
                'name'   => $this->session_name,
                'value'  => $isset ? $this->session_id:uniqid("mph_",true),
                'expire' => $flag ? $expire : time()-3600,
                'domain' => $domain,
                'path'   => $path,
                'secure' => $secure,
                'httponly'=>$http_only,
            );
            $this->set_cookie($cookieA);
            $this->session_id=$cookieA['value'];
        }
        
        public function sess_read()
        {
            self::$userdata = json_decode($this->memObj->get($this->session_id),true);
        }
            // --------------------------------------------------------------------
    
        /**
         * Write the session data
         *
         * @access        public
         * @return        void
         */
        public function sess_write($array)
        {
            foreach($array as $k => $v){
                self::$userdata[$k]=$v;
            }
            $data = json_encode(self::$userdata);
            if (get_class($this->memObj) === 'Memcached')
            {
                return $this->memObj->set($this->session_id, $data, $this->config_session['sess_memcached_ttl']);
            }
            elseif (get_class($this->memObj) === 'Memcache')
            {
                return $this->memObj->set($this->session_id, $data, 0, $this->config_session['sess_memcached_ttl']);
            }
            return FALSE;
        }
    
        // --------------------------------------------------------------------
    
        /**
         * Create a new session
         *
         * @access        public
         * @return        void
         */
        public function sess_create()
        {
            if($this->session_id == null)
            {
                $this->set_session_cookie();
                $this->init_data();
            }
            $this->sess_read();
            if($this->sess_check() === false){
                $this->set_session_cookie();
                $this->init_data();
            }
        }
    
        // --------------------------------------------------------------------
    
        /**
         * Destroy the current session
         *
         * @access        public
         * @return        void
         */
        public function sess_destroy()
        {
            self::$userdata = array();
            self::$destruct = false;
            $this->memObj->delete($this->session_id);
            return $this->set_session_cookie(false);
        }
        
        public function userdata($key='')
        {
            if(empty($key)){
                return self::$userdata;
            }
            if(isset(self::$userdata[$key])){
                return self::$userdata[$key];
            }else{
                return null;
            }
        }
        
        public function set_userdata($key,$val='')
        {
            if(is_array($key)){
                foreach($key as $kk => $vv){
                    self::$userdata[$kk]=$vv;
                }
            }else{
                self::$userdata[$key]=$val;
            }
        }
        
        protected function init_data()
        {
            $array['session_id']          = $this->session_id;
            $array['ip_address']          = $this->ip_address();
            $array['user_agent']          = substr($this->user_agent(), 0, 120);
            $array['last_activity']       = $this->now;
            $this->sess_write($array);
        }
        
        protected function mem_create()
        {
            if (class_exists('Memcached', FALSE))
            {
                $this->memObj = new Memcached();
            }
            elseif (class_exists('Memcache', FALSE))
            {
                $this->memObj = new Memcache();
            }
            else
            {
                log_message('error', 'Failed to create object for Memcached Cache; extension not loaded?');
                return FALSE;
            }
    
            foreach ($this->_memcache_conf as $name => $cache_server)
            {
                if ( ! array_key_exists('hostname', $cache_server))
                {
                    $cache_server['hostname'] = $this->_memcache_conf['default']['default_host'];
                }
    
                if ( ! array_key_exists('port', $cache_server))
                {
                    $cache_server['port'] = $this->_memcache_conf['default']['default_port'];
                }
    
                if ( ! array_key_exists('weight', $cache_server))
                {
                    $cache_server['weight'] = $this->_memcache_conf['default']['default_weight'];
                }
    
                if (get_class($this->memObj) === 'Memcache')
                {
                    // Third parameter is persistance and defaults to TRUE.
                    $this->memObj->addServer(
                        $cache_server['hostname'],
                        $cache_server['port'],
                        TRUE,
                        $cache_server['weight']
                    );
                }
                else
                {
                    $this->memObj->addServer(
                        $cache_server['hostname'],
                        $cache_server['port'],
                        $cache_server['weight']
                    );
                }
            }
            return TRUE;
        }
        
        public function __destruct()
        {
            if(self::$destruct){
                $data = json_encode(self::$userdata);
                if (get_class($this->memObj) === 'Memcached')
                {
                    return $this->memObj->set($this->session_id, $data, $this->config_session['sess_memcached_ttl']);
                }
                elseif (get_class($this->memObj) === 'Memcache')
                {
                    return $this->memObj->set($this->session_id, $data, 0, $this->config_session['sess_memcached_ttl']);
                }
            }
        }
        
        // --------------------------------------------------------------------
    
        /**
         * Does nothing for native sessions
         *
         * @access public
         * @return void
         */
        public function _sess_gc(){}
        
        
        public function ip_address()
        {
            $this->ip_address = $_SERVER['REMOTE_ADDR'];
    
            if ( ! $this->valid_ip($this->ip_address))
            {
                $this->ip_address = '0.0.0.0';
            }
    
            return $this->ip_address;
        }
        
        
        public function valid_ip($ip, $which = '')
        {
            $which = strtolower($which);
    
            // First check if filter_var is available
            if (is_callable('filter_var'))
            {
                switch ($which) {
                    case 'ipv4':
                        $flag = FILTER_FLAG_IPV4;
                        break;
                    case 'ipv6':
                        $flag = FILTER_FLAG_IPV6;
                        break;
                    default:
                        $flag = '';
                        break;
                }
    
                return (bool) filter_var($ip, FILTER_VALIDATE_IP, $flag);
            }
    
            if ($which !== 'ipv6' && $which !== 'ipv4')
            {
                if (strpos($ip, ':') !== FALSE)
                {
                    $which = 'ipv6';
                }
                elseif (strpos($ip, '.') !== FALSE)
                {
                    $which = 'ipv4';
                }
                else
                {
                    return FALSE;
                }
            }
    
            $func = '_valid_'.$which;
            return $this->$func($ip);
        }
        
        protected function _valid_ipv4($ip)
        {
            $ip_segments = explode('.', $ip);
    
            // Always 4 segments needed
            if (count($ip_segments) !== 4)
            {
                return FALSE;
            }
            // IP can not start with 0
            if ($ip_segments[0][0] == '0')
            {
                return FALSE;
            }
    
            // Check each segment
            foreach ($ip_segments as $segment)
            {
                // IP segments must be digits and can not be
                // longer than 3 digits or greater then 255
                if ($segment == '' OR preg_match("/[^0-9]/", $segment) OR $segment > 255 OR strlen($segment) > 3)
                {
                    return FALSE;
                }
            }
    
            return TRUE;
        }
    
        // --------------------------------------------------------------------
    
        /**
        * Validate IPv6 Address
        *
        * @access    protected
        * @param    string
        * @return    bool
        */
        protected function _valid_ipv6($str)
        {
            // 8 groups, separated by :
            // 0-ffff per group
            // one set of consecutive 0 groups can be collapsed to ::
    
            $groups = 8;
            $collapsed = FALSE;
    
            $chunks = array_filter(
                preg_split('/(:{1,2})/', $str, NULL, PREG_SPLIT_DELIM_CAPTURE)
            );
    
            // Rule out easy nonsense
            if (current($chunks) == ':' OR end($chunks) == ':')
            {
                return FALSE;
            }
    
            // PHP supports IPv4-mapped IPv6 addresses, so we'll expect those as well
            if (strpos(end($chunks), '.') !== FALSE)
            {
                $ipv4 = array_pop($chunks);
    
                if ( ! $this->_valid_ipv4($ipv4))
                {
                    return FALSE;
                }
    
                $groups--;
            }
    
            while ($seg = array_pop($chunks))
            {
                if ($seg[0] == ':')
                {
                    if (--$groups == 0)
                    {
                        return FALSE;    // too many groups
                    }
    
                    if (strlen($seg) > 2)
                    {
                        return FALSE;    // long separator
                    }
    
                    if ($seg == '::')
                    {
                        if ($collapsed)
                        {
                            return FALSE;    // multiple collapsed
                        }
    
                        $collapsed = TRUE;
                    }
                }
                elseif (preg_match("/[^0-9a-f]/i", $seg) OR strlen($seg) > 4)
                {
                    return FALSE; // invalid segment
                }
            }
    
            return $collapsed OR $groups == 1;
        }
        
        protected function set_cookie($name = '', $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE)
        {
            if (is_array($name))
            {
                // always leave 'name' in last place, as the loop will break otherwise, due to $$item
                foreach (array('value', 'expire', 'domain', 'path', 'prefix', 'secure', 'name') as $item)
                {
                    if (isset($name[$item]))
                    {
                        $$item = $name[$item];
                    }
                }
            }
    
            if ($prefix == '' AND $this->config_session['cookie_prefix'] != '')
            {
                $prefix = $this->config_session['cookie_prefix'];
            }
            if ($domain == '' AND $this->config_session['cookie_domain'] != '')
            {
                $domain = $this->config_session['cookie_domain'];
            }
            if ($path == '/' AND $this->config_session['cookie_path'] != '/')
            {
                $path = $this->config_session['cookie_path'];
            }
            if ($secure == FALSE AND $this->config_session['cookie_secure'] != FALSE)
            {
                $secure = $this->config_session['cookie_secure'];
            }
    
            if ( ! is_numeric($expire))
            {
                $expire = time() - 86500;
            }
            else
            {
                $expire = ($expire > 0) ? time() + $expire : 0;
            }
    
            setcookie($prefix.$name, $value, $expire, $path, $domain, $secure);
        }
        
        protected function user_agent()
        {
            return ( ! isset($_SERVER['HTTP_USER_AGENT'])) ? FALSE : $_SERVER['HTTP_USER_AGENT'];
        }
    }

    配置文件与上面的类文件同目录:

    <?php
    $config_session['cookie_prefix']    = "";
    $config_session['cookie_domain']    = ".mypharma.com";
    $config_session['cookie_path']        = "/";
    $config_session['cookie_secure']    = FALSE;
    $config_session['cookie_httponly']    = FALSE;
    
    $config_session['sess_cookie_name']        = 'mphsess';
    $config_session['sess_expiration']            = 0;
    $config_session['sess_expire_on_close']    = true;
    $config_session['sess_memcached_ttl']      = 10*24*60*60;
    $config_session['sess_match_ip']            = TRUE;
    $config_session['sess_match_useragent']    = TRUE;
    
    $_memcache_conf = array(
        '23'=>array(
            'hostname'=>'192.168.11.23',
            'port'=>11211,
            'weight'=>1
        )
    );
  • 相关阅读:
    803ESP32_SDK开发手机连接ESP32的热点,使用微信小程序查看摄像头图像(WiFi视频小车,局域网视频监控)
    202HC32F460(华大)+Air724UG(4G GPRS)基本控制篇(阿里云物联网平台)设备使用一型一密动态注册方式连接云平台,并使用物模型Topic上报温湿度数据
    201CH579M学习开发以太网例程DHCP
    002CH582M学习开发官方资料学习说明,开发板USB,蓝牙通信测试
    201HC32F460(华大)+Air724UG(4G GPRS)基本控制篇(阿里云物联网平台)设备使用一机一密方式连接云平台,并使用物模型Topic上报温湿度数据
    200CH579M学习开发以太网例程网络指示灯GPIO选择, 检测网线连接状态
    401HC32F460(华大)+Air724UG(4G GPRS)基本控制篇(阿里云物联网平台)Android扫码绑定Air724UG并通过阿里云物联网平台实现远程通信控制
    详解Spring中的Event事件处理机制和原理
    linux系统里/opt目录和/usr/local目录的区别
    gorm系列创建记录及字段默认值
  • 原文地址:https://www.cnblogs.com/kudosharry/p/3382131.html
Copyright © 2020-2023  润新知