即使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
)
);

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

  1. 分布式Session共享(一):tomcat+redis实现session共享

    一.前言 本文主要测试redis实现session共享的实现方式,不讨论如何让nginx参与实现负载均衡等. 二.环境配置 本测试在Window下进行 name version port Tomcat ...

  2. 分布式Session共享(二):tomcat+memcached实现session共享

    一.前言 本文主要测试memcached实现session共享的实现方式,不讨论如何让nginx参与实现负载均衡等. 二.环境配置 本测试在Window下进行 name version port To ...

  3. ajax 发送json数据时为什么需要设置contentType: "application/json”

    1. ajax发送json数据时设置contentType: "application/json”和不设置时到底有什么区别? contentType: "application/j ...

  4. ajax发送json数据时为什么需要设置contentType: "application/json”

    1. ajax发送json数据时设置contentType: "application/json”和不设置时到底有什么区别?contentType: "application/js ...

  5. Tomcat利用MSM实现Session共享方案解说

    Session共享有多种解决方法,常用的有四种:1)客户端Cookie保存2)服务器间Session同步3)使用集群管理Session(如MSM) 4)把Session持久化到数据库 针对上面Sess ...

  6. 分布式中使用Redis实现Session共享(二)

    上一篇介绍了一些redis的安装及使用步骤,本篇开始将介绍redis的实际应用场景,先从最常见的session开始,刚好也重新学习一遍session的实现原理.在阅读之前假设你已经会使用nginx+i ...

  7. Tomcat7基于Redis的Session共享实战二

    目前,为了使web能适应大规模的访问,需要实现应用的集群部署.集群最有效的方案就是负载均衡,而实现负载均衡用户每一个请求都有可能被分配到不固定的服务器上,这样我们首先要解决session的统一来保证无 ...

  8. 集群间Session共享问题解决方案

    两个基本概念的生命周期 session: 当新客户端发现一个HTTP请求时服务端会创建一个session.并分配一个sessionID作为服务端来客户端的识别,session对象会保存在服务端.此时s ...

  9. 使用nginx做负载均衡的session共享问题

    查了一些资料,看了一些别人写的文档,总结如下,实现nginx session的共享PHP服务器有多台,用nginx做负载均衡,这样同一个IP访问同一个页面会被分配到不同的服务器上,如果session不 ...

随机推荐

  1. FastReport报表

    http://www.fastreportcn.com/product/FASTREPORT_dotNET.html

  2. 安装mysql之后,存入中文出现乱码

    如图显示:安装mysql之后,存入中文出现乱码 解决方案: 找到如图的文件位置 打开进行如图的修改: 结果:

  3. Dom新find

    1.HTML标签和属性是不区分大小写的,但JS是区分大小写的:所以(1)HTML专有的接口的属性应该以小写字母开头,如果属性名由多个单词构成,第二个及接下来的每个单词的首字母都要大写.(2)有些HTM ...

  4. copy

    拷贝文件,不覆盖重复文件 yes no|cp -i a b

  5. 关于linux下rar文件的解压缩操作

    在linux系统下.本身没有对rar文件操作的命令,如果需要对rar格式的文件操作,我们需要安装第三方的软件rar以及unrar. 1.linux下rar管理软件下载的官方地址为:http://www ...

  6. hdu2023 求平均成绩 ~~很闲~~~

    #include<iostream> #include<stdio.h> #include<math.h> #include<string.h> #in ...

  7. iOS 应用内付费(IAP)开发步骤

    折腾好几天,原来是税务信息没有填写,哎...  国内就是好啊,没有这些麻烦的事情...  :) 等24小时,等税务的审核结果...     有结论了 才能测试内购.... 如果税务信息没有填写完毕,p ...

  8. web.xml文件中加载顺序的优先级

    在项目中总会遇到一些关于加载的优先级问题,近期也同样遇到过类似的,所以自己查找资料总结了下,下面有些是转载其他人的,毕竟人家写的不错,自己也就不重复造轮子了,只是略加点了自己的修饰. 首先可以肯定的是 ...

  9. Minifilter微过滤框架:框架介绍以及驱动层和应用层的通讯

    minifilter是sfilter后微软推出的过滤驱动框架.相比于sfilter,他更容易使用,需要程序员做的编码更简洁. 系统为minifilter专门制作了一个过滤管理器,这个管理器本身其实是一 ...

  10. module.xml 快捷代码

    以下内容为淘宝装修模块描述文件(module.xml)快捷代码块,可以快速调整模块信息,详解请查阅>> http://open.taobao.com/doc/detail.htm?id=1 ...