我们先来看一下cls_seesion类是如何被调用的:一个最简单的例子是通过admin/index.php进入到admin/includes/init.php,在init.php我们可以找到如下代码:

require(ROOT_PATH . 'includes/cls_session.php');
/*
$db 数据库对象
$ecs->table('sessions')=>`ecshop`.`ecs_sessions`//数据库名.数据表名
$ecs->table('sessions_data')=>`ecshop`.`ecs_sessions_data`
'ECSCP_ID'=>session名称
*/
$sess = new cls_session($db, $ecs->table('sessions'), $ecs->table('sessions_data'), 'ECSCP_ID');

所以,cls_session类是完成初始化工作的一部分。它的功能主要是在客户端生成cookie,进行session的验证,并把一些会话数据插入到数据库中。下面我们来研究每段代码的执行流程以及实现的功能:

//下面的判断语句是为了防止通过地址直接访问该页面
if (!defined('IN_ECS'))
{die('Hacking attempt');
}class cls_session
{var $db             = NULL;//数据库连接资源句柄var $session_table  = '';//会话表名:ecs_sessionvar $max_life_time  = 1800; // SESSION 生命周期var $session_name   = '';//会话名:在客户端表示为ESCCP_IDvar $session_id     = '';//会话IDvar $session_expiry = '';//会话过期时间戳var $session_md5    = '';//下面的三个参数都为setcookie中的参数var $session_cookie_path   = '/';var $session_cookie_domain = '';var $session_cookie_secure = false;var $_ip   = '';//客户端真实IPvar $_time = 0;//当前时间function __construct(&$db, $session_table, $session_data_table, $session_name = 'ECS_ID', $session_id = ''){$this->cls_session($db, $session_table, $session_data_table, $session_name, $session_id);}//构造方法function cls_session(&$db, $session_table, $session_data_table, $session_name = 'ECS_ID', $session_id = ''){$GLOBALS['_SESSION'] = array();//定义一个全局的_SESSION数组变量//下面的三个条件语句都是为了给setcookie函数的三个参数做初始化工作//cookie在服务器端的有效路径如果该参数设为"/",则它在整个//domain(域)内有效,若设为"/11",它就在domain下的/11目录及其子目录内有效,默认为当前目录if (!empty($GLOBALS['cookie_path']))//$GLOBALS['cookie_path']='/'{$this->session_cookie_path = $GLOBALS['cookie_path'];}else{$this->session_cookie_path = '/';}//cookie的有效域名if (!empty($GLOBALS['cookie_domain']))//$GLOBALS['cookie_domain']=''{$this->session_cookie_domain = $GLOBALS['cookie_domain'];}else{$this->session_cookie_domain = '';}//cookie的安全传输方式,1为https,0为http或httpsif (!empty($GLOBALS['cookie_secure'])){$this->session_cookie_secure = $GLOBALS['cookie_secure'];}else{$this->session_cookie_secure = false;}$this->session_name       = $session_name;$this->session_table      = $session_table;$this->session_data_table = $session_data_table;$this->db  = &$db;$this->_ip = real_ip();//lib_base基础函数库中的一个获取客户端真实ip的自定义函数if ($session_id == '' && !empty($_COOKIE[$this->session_name])){   //再次载入页面的时候执行以下语句,即客户端已存在COOKIE存在$this->session_id = $_COOKIE[$this->session_name];}else{$this->session_id = $session_id;}//第一次载入页面或客户端没有COOKIE时,$this->session_id为空if ($this->session_id){ //对客户端的COOKIE进行验证,防止伪造COOKIE//如果不对gen_session_key函数做一些自己的修改,黑客很容易就可以绕过这部分的验证$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 = '';}}$this->_time = time();if ($this->session_id){    //客户端的COOKIE已存在才会执行,否则会执行else部分,重新生成COOKIE$this->load_session();}else{//第一次载入页面或$this->session_id为空时执行这部分代码$this->gen_session_id();//得到一个唯一的ID,并把它插入数据库//cookie和数据库里的字段sesskey存的不一样,sesskey只存$this->session_id  32位//cookie名为ECSCP_ID,值为$this->session_id. $this->gen_session_key($this->session_id) 40位, 过期时间设为0setcookie($this->session_name, $this->session_id . $this->gen_session_key($this->session_id), 0, $this->session_cookie_path, $this->session_cookie_domain, $this->session_cookie_secure);}//PHP程序执行完成后执行该函数register_shutdown_function(array(&$this, 'close_session'));}/**第一次载入页面的时候这个这个函数会执行*生成一个唯一的session_id并插入数据库*/function gen_session_id(){$this->session_id = md5(uniqid(mt_rand(), true));return $this->insert_session();}function gen_session_key($session_id){static $ip = '';if ($ip == ''){$ip = substr($this->_ip, 0, strrpos($this->_ip, '.'));}//crc32()生成32为的循环冗余校验码,sprintf后只取前8位//数据库中的sesskey少的就是这八位return sprintf('%08x', crc32(ROOT_PATH . $ip . $session_id));}/*插入数据库函数*/function insert_session(){return $this->db->query('INSERT INTO ' . $this->session_table . " (sesskey, expiry, ip, data) VALUES ('" . $this->session_id . "', '". $this->_time ."', '". $this->_ip ."', 'a:0:{}')");}function load_session(){$session = $this->db->getRow('SELECT userid, adminid, user_name, user_rank, discount, email, data, expiry FROM ' . $this->session_table . " WHERE sesskey = '" . $this->session_id . "'");//执行到这一步,说明用户的客户端存在名为ECSCP_ID的COOKIE,如果$session为空,很可能这个cookie是伪造的if (empty($session)){$this->insert_session();$this->session_expiry = 0;$this->session_md5    = '40cd750bba9870f18aada2478b24840a';$GLOBALS['_SESSION']  = array();}else{   if (!empty($session['data']) && $this->_time - $session['expiry'] <= $this->max_life_time){   //如果会话没有过期$this->session_expiry = $session['expiry'];$this->session_md5    = md5($session['data']);$GLOBALS['_SESSION']  = unserialize($session['data']);$GLOBALS['_SESSION']['user_id'] = $session['userid'];$GLOBALS['_SESSION']['admin_id'] = $session['adminid'];$GLOBALS['_SESSION']['user_name'] = $session['user_name'];$GLOBALS['_SESSION']['user_rank'] = $session['user_rank'];$GLOBALS['_SESSION']['discount'] = $session['discount'];$GLOBALS['_SESSION']['email'] = $session['email'];}else{$session_data = $this->db->getRow('SELECT data, expiry FROM ' . $this->session_data_table . " WHERE sesskey = '" . $this->session_id . "'");if (!empty($session_data['data']) && $this->_time - $session_data['expiry'] <= $this->max_life_time){$this->session_expiry = $session_data['expiry'];$this->session_md5    = md5($session_data['data']);$GLOBALS['_SESSION']  = unserialize($session_data['data']);$GLOBALS['_SESSION']['user_id'] = $session['userid'];$GLOBALS['_SESSION']['admin_id'] = $session['adminid'];$GLOBALS['_SESSION']['user_name'] = $session['user_name'];$GLOBALS['_SESSION']['user_rank'] = $session['user_rank'];$GLOBALS['_SESSION']['discount'] = $session['discount'];$GLOBALS['_SESSION']['email'] = $session['email'];}else{$this->session_expiry = 0;$this->session_md5    = '40cd750bba9870f18aada2478b24840a';$GLOBALS['_SESSION']  = array();}}}}function update_session(){$adminid = !empty($GLOBALS['_SESSION']['admin_id']) ? intval($GLOBALS['_SESSION']['admin_id']) : 0;$userid  = !empty($GLOBALS['_SESSION']['user_id'])  ? intval($GLOBALS['_SESSION']['user_id'])  : 0;$user_name  = !empty($GLOBALS['_SESSION']['user_name'])  ? trim($GLOBALS['_SESSION']['user_name'])  : 0;$user_rank  = !empty($GLOBALS['_SESSION']['user_rank'])  ? intval($GLOBALS['_SESSION']['user_rank'])  : 0;$discount  = !empty($GLOBALS['_SESSION']['discount'])  ? round($GLOBALS['_SESSION']['discount'], 2)  : 0;$email  = !empty($GLOBALS['_SESSION']['email'])  ? trim($GLOBALS['_SESSION']['email'])  : 0;unset($GLOBALS['_SESSION']['admin_id']);unset($GLOBALS['_SESSION']['user_id']);unset($GLOBALS['_SESSION']['user_name']);unset($GLOBALS['_SESSION']['user_rank']);unset($GLOBALS['_SESSION']['discount']);unset($GLOBALS['_SESSION']['email']);$data        = serialize($GLOBALS['_SESSION']);$this->_time = time();//第一次载入$GLOBALS['_SESSION']、session_md5和session_expiry为空,$data为a:0:{}也为空if ($this->session_md5 == md5($data) && $this->_time < $this->session_expiry + 10){return true;}$data = addslashes($data);//即$data不为a:0:{}if (isset($data{255})){$this->db->autoReplace($this->session_data_table, array('sesskey' => $this->session_id, 'expiry' => $this->_time, 'data' => $data), array('expiry' => $this->_time,'data' => $data));$data = '';}return $this->db->query('UPDATE ' . $this->session_table . " SET expiry = '" . $this->_time . "', ip = '" . $this->_ip . "', userid = '" . $userid . "', adminid = '" . $adminid . "', user_name='" . $user_name . "', user_rank='" . $user_rank . "', discount='" . $discount . "', email='" . $email . "', data = '$data' WHERE sesskey = '" . $this->session_id . "' LIMIT 1");}function close_session(){$this->update_session();if (mt_rand(0, 2) == 2){//删除掉过期的会话$this->db->query('DELETE FROM ' . $this->session_data_table . ' WHERE expiry < ' . ($this->_time - $this->max_life_time));}if ((time() % 2) == 0){return $this->db->query('DELETE FROM ' . $this->session_table . ' WHERE expiry < ' . ($this->_time - $this->max_life_time));}return true;}function delete_spec_admin_session($adminid){if (!empty($GLOBALS['_SESSION']['admin_id']) && $adminid){return $this->db->query('DELETE FROM ' . $this->session_table . " WHERE adminid = '$adminid'");}else{return false;}}function destroy_session(){$GLOBALS['_SESSION'] = array();setcookie($this->session_name, $this->session_id, 1, $this->session_cookie_path, $this->session_cookie_domain, $this->session_cookie_secure);if (!empty($GLOBALS['ecs'])){$this->db->query('DELETE FROM ' . $GLOBALS['ecs']->table('cart') . " WHERE session_id = '$this->session_id'");}$this->db->query('DELETE FROM ' . $this->session_data_table . " WHERE sesskey = '" . $this->session_id . "' LIMIT 1");return $this->db->query('DELETE FROM ' . $this->session_table . " WHERE sesskey = '" . $this->session_id . "' LIMIT 1");}function get_session_id(){return $this->session_id;}function get_users_count(){return $this->db->getOne('SELECT count(*) FROM ' . $this->session_table);}
}

ecshop源码分析:会话类cls_session相关推荐

  1. 转载 ECSHOP 源码分析(includes/init.php)

    Code: 转载  ECSHOP 源码分析(includes/init.php) 收藏 <?php /** * ECSHOP 前台公用文件 * ========================= ...

  2. ecshop源码分析:smarty模板类

    花了差不多3天半的时间,基本上把ecshop1400多行的模板类源码阅读完毕.从构造函数一行一行的阅读下去,遇到方法的调用便进去,遇到返回值又回到调用它的地方,这样来回不知道多少遍,每次阅读都让我心奋 ...

  3. spring Quartz 源码分析--触发器类CronTriggerBean源码剖析

    前面我们讲到了Quartz框架在项目中的实现,在Quartz中的重要API有两个重要的触发器类:CronTrigger 和SimpleTrigger 在Quartz框架中这两个触发器都继承了一个抽象基 ...

  4. Tensorflow 源码分析-会话与线程池之间的关系

    1. Tensorflow 的sessionFactory 创建新的会话,tensorflow使用了多工厂模式,在不同的场景下使用不同的工厂, 使用什么工厂模式由传递进来的SessionOptions ...

  5. springSecurity源码分析——DelegatingFilterProxy类的作用

    http://www.cnblogs.com/hzhuxin/archive/2011/12/19/2293730.html 使用过springSecurity的朋友都知道,首先需要在web.xml进 ...

  6. ecshop index.php,ecshop  源码分析01 (index.php)

    //ecshop 2.7.2 // define是php里定义常量用的.第一个参数是常量名,第二个是常量的值. // 它定义这个常量的作用是防止被引用文件的非法载入. // 根据某人的说法, 挂个鸟牌 ...

  7. MariaDB源码分析——CONNECT类

    当主线程accept新连接之后,会调用handle_accepted_socket函数,申请CONNECT类对象,调用create_new_thread函数,该函数为CONNECT类对象的thread ...

  8. ecshop源码分析——静态缓存static_c…

    http://guozhiwei.javaeye.com/blog/673291 http://www.phpall.cn static_caches缓存文件 存放在ecshop/temp/stati ...

  9. Hadoop3.2.1 【 HDFS 】源码分析 :FSDirectory类解析

    Table of Contents 一.前言. 二.构造方法 三.常量 四.方法 一.前言. Namenode最重要的两个功能之一就是维护整个文件系统的目录树(即命名空间namesystem) . H ...

  10. 【Groovy】闭包 Closure ( 闭包类 Closure 简介 | this、owner、delegate 成员赋值及源码分析 )

    文章目录 总结 一.闭包类 Closure 简介 二.闭包类 Closure 中 this.owner.delegate 成员 源码分析 三.分析编译后的字节码文件内容 总结 在闭包中 , 打印 th ...

最新文章

  1. SQLServer 中Case When的用法
  2. php拼音模糊查询,PHP模糊查询技术实例分析【附源码下载】
  3. 对比直立车模控制中的互补滤波、Karlman滤波和参考滤波方案
  4. CORE ANIMATION的学习备忘录
  5. java中io流中显示中文_关于JAVA中IO流相关问题概述
  6. github上的linux项目,克隆GitHub上项目的非Master分支
  7. java 从网络Url中下载文件
  8. 轻量又高效,Apache Shiro 你值得拥有!
  9. html 模板中的for循环,Flask模板引擎中的For循环
  10. 多进程与多线程通信同步机制
  11. 另类架构师:在国企涂肥皂水、考研被调剂、在阿里跟十八罗汉当同事……
  12. 设置XMLHttpRequest“ withCredentials”属性问题,axios请求不成功
  13. python compile函数_python 内置函数 compile()
  14. 微信小程序开发语言和“前端三件套”的异同点
  15. CUDA: Occupancy(占用率)详解
  16. Dream_Chaser队训练赛第一场 K题
  17. 分布式监控apm_Datadog:APM和分布式跟踪的新Java支持
  18. PLC的编程语言跟CNC的编程语言有什么区别?
  19. 哲学家进餐_我如何通过预算学习计划进餐
  20. postgresql + postgis 离线安装

热门文章

  1. 计算机多媒体软件应用,论计算机实验多媒体软件应用
  2. 通达OA CRM扫描枪条码录入
  3. 老鸟成长之路:菜鸟入门八种安全工具(转)
  4. 自动锁定计算机怎么设置,win10如何设置自动锁定屏幕_win10设置自动锁屏的步骤...
  5. 网络安全—御剑后台扫描珍藏版
  6. Android物联网应用程序开发(智慧城市)—— 购物信息的存储界面开发
  7. win hook codeproject
  8. Java实现图书管理系统(新手友好)
  9. html360se,360浏览器发布SE版本
  10. 2021美赛MCM选题