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
)
);
session共享,格式json,php不能简单的设置session.serialize_handler=json,目前只有php,wddx(xml),安装扩展后还有igbinary(二进制)的更多相关文章
- 分布式Session共享(一):tomcat+redis实现session共享
一.前言 本文主要测试redis实现session共享的实现方式,不讨论如何让nginx参与实现负载均衡等. 二.环境配置 本测试在Window下进行 name version port Tomcat ...
- 分布式Session共享(二):tomcat+memcached实现session共享
一.前言 本文主要测试memcached实现session共享的实现方式,不讨论如何让nginx参与实现负载均衡等. 二.环境配置 本测试在Window下进行 name version port To ...
- ajax 发送json数据时为什么需要设置contentType: "application/json”
1. ajax发送json数据时设置contentType: "application/json”和不设置时到底有什么区别? contentType: "application/j ...
- ajax发送json数据时为什么需要设置contentType: "application/json”
1. ajax发送json数据时设置contentType: "application/json”和不设置时到底有什么区别?contentType: "application/js ...
- Tomcat利用MSM实现Session共享方案解说
Session共享有多种解决方法,常用的有四种:1)客户端Cookie保存2)服务器间Session同步3)使用集群管理Session(如MSM) 4)把Session持久化到数据库 针对上面Sess ...
- 分布式中使用Redis实现Session共享(二)
上一篇介绍了一些redis的安装及使用步骤,本篇开始将介绍redis的实际应用场景,先从最常见的session开始,刚好也重新学习一遍session的实现原理.在阅读之前假设你已经会使用nginx+i ...
- Tomcat7基于Redis的Session共享实战二
目前,为了使web能适应大规模的访问,需要实现应用的集群部署.集群最有效的方案就是负载均衡,而实现负载均衡用户每一个请求都有可能被分配到不固定的服务器上,这样我们首先要解决session的统一来保证无 ...
- 集群间Session共享问题解决方案
两个基本概念的生命周期 session: 当新客户端发现一个HTTP请求时服务端会创建一个session.并分配一个sessionID作为服务端来客户端的识别,session对象会保存在服务端.此时s ...
- 使用nginx做负载均衡的session共享问题
查了一些资料,看了一些别人写的文档,总结如下,实现nginx session的共享PHP服务器有多台,用nginx做负载均衡,这样同一个IP访问同一个页面会被分配到不同的服务器上,如果session不 ...
随机推荐
- ==和equals的区别
== :是判断两个变量或实例是不是指向同一个内存空间equals :是判断两个变量或实例所指向的内存空间的值是不是相同 结论:欲比较栈中数据是否相等,请用= =:欲比较堆中数据是否相等,请用equal ...
- The first day of HTML
这是韩顺平老师的<轻松搞定网页设计(html.css.js)>,讲的还凑合,仅作入门.决定还是做好笔记,记录学习的过程,这是HTML的第一天. HTML(HyperText Mark-up ...
- JDBC第二次学习
脑子太笨,必须得记录下来一些文字,方便回来查询. 这是我的第二次学习JDBC的笔记,看的是传智播客——李勇老师的JDBC系列,已看到第23集. 分析在实际项目中该如何应用JDBC 一个简单用户相关的数 ...
- JS之事件(一)
事件:交互 异步监听,不是JS引擎监听的 一.绑定 1.ele.onxxxx(eg:onclick) = function (e) { //回调函数/事件处理函数 } 兼容性很好,但同一个事件仅能绑定 ...
- spring_150801_autowired_qualifier
新建java project工程,建src.conf.test源码文件夹,导入相关包,需要spring的相关jar包和common-logging相关jar包 接口Service: package c ...
- yafeilinux.com的开源项目非常好的东西
转自:http://www.yafeilinux.com/?page_id=9 声明:我们网站的资源可以自由下载,转载,但是不能用作商业用途.如有问题请联系我们www.yafeilinux.com . ...
- iOS keyChain
keychain在ios中是保存在sqlite数据库中的. 这个数据库文件的位置: 真机: /private/var/Keychains/keychain-2.db 虚拟机: /Users/USER- ...
- mysql 生成批量存储过程
CREATE PROCEDURE `BatchInsert`(IN init INT, IN loop_time INT)BEGIN DECLARE Var INT; DECLARE ID INT; ...
- Spring Boot MyBatis 通用Mapper插件集成
Mybatis在使用过程中需要三个东西,每张表对应一个XXMapper.java接口文件,每张表对应一个XXMapper.xml文件,每张表对应一个Entity的Java文件. 其中XXMappe ...
- USACO Section 2.4: Fractions to Decimals
乍看题目感觉有难度,实际分析后其实是道简单题 /* ID: yingzho1 LANG: C++ TASK: fracdec */ #include <iostream> #include ...