ECMALL session跨域实现解析 原创

ECMALL session跨域实现

应用举例: 在data/config.inc.php 中 设置COOKIE_DOMAIN cookie作用域为 .ljlj.cc 后,在 mall.ljlj.cc用户登录后 在 products.ljlj.cc中可以获取到cookie中 ECM_ID.
以ECM_ID前32为字符串为主键 到 ecm_sessions数据表中即可查询到mall.ljlj.cc登录用户的session信息
session 核心文件
文件位置: includes/libraries/session.lib.php 定义session类 SessionProcessor

类中构造函数调用SessionProcessor()方法自定义了ecmall自己的session会话规则
(1) 自定义session会话

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
session_set_save_handler(   

array (& $this, "_sess_open"),在运行session_start()时执行

array (& $this, "_sess_close"),所有session操作完后被执行 

array (& $this, "_sess_read"),在运行session_start()时执行,因为在session_start时,会去read当前session数据

array (& $this, "_sess_write"),此方法在脚本结束和使用session_write_close()强制提交SESSION数据时执行

array (& $this, "_sess_destroy"),在运行session_destroy()时执行

array (& $this, "_sess_gc")时机是在open,read之后,session_start会相继执行open,read和gc

);

(2)处理session作用域 作用路径已经 过期时间 实现session跨子域 需要在data/config.inc.php中对 COOKIE_PATH(作用路径) COOKIE_DOMAIN(作用域)进行设置 例: COOKIE_DOMAIN = ‘.ljlj.cc’

1
2
3
4
5
6
7
8
9
$this->gmtime = gmtime();

$this->max_life_time = 1440; 过期时间

$this->session_cookie_path = COOKIE_PATH; 作用路径

$this->session_cookie_domain = COOKIE_DOMAIN; 作用域

//如果开启二级域名,且未设置COOKIE作用域,则缺省为上级域
1
2
3
4
5
6
7
8
9
10
11
12
13
14
if(defined('ENABLED_SUBDOMAIN')&&ENABLED_SUBDOMAIN && !COOKIE_DOMAIN)
{
$tmp_arr = parse_url(SITE_URL);
if (count(explode('.', $tmp_arr['host'])) > 2)
{
$cookie_domain = substr($tmp_arr['host'], strpos($tmp_arr['host'], '.'));
}
else
{
// 形如ecmall.com这样的域名
$cookie_domain = '.' . $tmp_arr['host'];
}
$this->session_cookie_domain = $cookie_domain;
}

(3)判断session id为空 但是cookie已经设置 直接取cookie中session id ($session_id默认设置为空)

1
2
3
4
5
6
7
8
9
if($session_id==''&& !empty($_COOKIE[$this->session_name])

{
$this->session_id = $_COOKIE[$this->session_name];
}
else
{
$this->session_id = $session_id;
}

(4) 如果session id存在 那么截取session id中的后8位验证字符串进行验证

1
2
3
4
5
6
7
8
9
10
11
12
13
if ($this->session_id)
{
$tmp_session_id = substr($this->session_id, 0, 32);

if($this->gen_session_key($tmp_session_id)==substr($this->session_id, 32))
{
$this->session_id = $tmp_session_id;
}
else
{
$this->session_id = '';
}
}

(5) 验证字符串 由gen_session_key()函数 产生
sprintf(‘%08x’, crc32(!empty($_SERVER[‘HTTP_USER_AGENT’]) ? $_SERVER[‘HTTP_USER_AGENT’] . ROOT_PATH . $ip . $session_id : ROOT_PATH . $ip . $session_id));

(6) 如果session id 不存在则生成新的 session_id( 32位session_id加8位验证字符串)
调用 gen_session_key() 产生8位16进制验证字符串拼接在session_id后面 存储在cookie中 例: [“ECM_ID”]=> string(40) “8bfc72b2919c2d5f8db0785a24e55fd535ef3589”(后8位为验证字符串)

1
2
3
4
5
6
if (!$this->session_id)
{
$this->gen_session_id(); 为$this->session_id赋值
session_id($this->session_id.$this->gen_session_key($this->session_id));

}

(7) Session_id 生成函数 gen_session_id() 生成规则为 MD5加密 uniqid(随机数)

1
2
3
4
5
6
function gen_session_id()
{
$this->session_id = md5(uniqid(mt_rand(), true));

return $this->insert_session();
}

(8) insert_session()方法负责将生成的session插入数据库 db_mall库下 ecm_sessions 表 主键为sesskey (32位 session_id)

(9) _sess_write(32位session_id,用户信息)方法负责update ecm_sessions表中对应sesskey信息

1
登录后用户session信息 :例:captcha|s:8:"Z3dydQ==";user_info|a:7:{s:7:"user_id";s:4:"5315";s:9:"user_name";s:6:"wewewe";s:8:"reg_time";s:10:"1436267397";s:10:"last_login";s:10:"1436411543";s:7:"last_ip";s:9:"127.0.0.1";s:8:"store_id";N;s:10:"activation";N;

退出登录后 session信息:
例:captcha|s:8:”Z3dydQ==”;”