加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

CI框架Session.php源码分析

发布时间:2020-12-13 02:07:31 所属栏目:PHP教程 来源:网络整理
导读:《PHP实例:CI框架Session.php源码分析》要点: 本文介绍了PHP实例:CI框架Session.php源码分析,希望对您有用。如果有疑问,可以联系我们。 PHP教程 CI的Session并不是原生的session,正是我前面所有的cookie based session,另外,CI可以根据用户选择配置是否

《PHP实例:CI框架Session.php源码分析》要点:
本文介绍了PHP实例:CI框架Session.php源码分析,希望对您有用。如果有疑问,可以联系我们。

PHP教程CI的Session并不是原生的session,正是我前面所有的cookie based session,另外,CI可以根据用户选择配置是否将session存入数据库中,本人很喜欢这个功能,还有就是“闪出数据”的功能,既闪出数据只是对下次服务器哀求可以,之后就会被自动清除.常见使用方法有:

PHP教程$this->session->set_userdata('some_name','some_value'); //设置session数据

PHP教程$this->session->userdata('item'); //获取session数据

PHP教程$this->session->unset_userdata('some_name'); //删除session数据

PHP教程$this->session->sess_destroy(); //销毁session数据

PHP教程$this->session->set_flashdata('item','value'); //设置闪存数据

PHP教程$this->session->flashdata('item'); //获取闪存数据

PHP教程$this->session->keep_flashdata('item');? //保留闪存数据

代码如下:

/**
?* CI是 session based cookie
?*/
class CI_Session {
?var $sess_encrypt_cookie??= FALSE;? //是否对session加密
?var $sess_use_database???= FALSE; //是否将session存入数据库
?var $sess_table_name???= ''; //session存入数据的表名
?var $sess_expiration???= 7200; //session的过期时间
?var $sess_expire_on_close??= FALSE; //当浏览器窗口关闭时是否自动使session过期
?var $sess_match_ip????= FALSE;//是否通过用户的IP地址来读取 session 的数据
?var $sess_match_useragent??= TRUE; //是否要按照对应的 User Agent 来读取 session 数据.
?var $sess_cookie_name???= 'ci_session'; //cookie名称
?var $cookie_prefix????= ''; //cookie前缀
?var $cookie_path????= ''; //cookie路径
?var $cookie_domain????= ''; //cookie作用域
?var $cookie_secure????= FALSE; //是否在安全的https协议下才有效
?var $sess_time_to_update??= 300; //session cookie多久更新一次
?var $encryption_key????= ''; //加密key
?var $flashdata_key????= 'flash';
?var $time_reference????= 'time';
?var $gc_probability????= 5;? //回收session的能力
?var $userdata?????= array(); //用户session数据保存变量
?var $CI; //CI超级句柄
?var $now;? //当前时间
?public function __construct($params = array())
?{
??log_message('debug',"Session Class Initialized");
??// 获取CI超级类
??$this->CI =& get_instance();
??// 获取config文件中的配置数据
??foreach (array('sess_encrypt_cookie','sess_use_database','sess_table_name','sess_expiration','sess_expire_on_close','sess_match_ip','sess_match_useragent','sess_cookie_name','cookie_path','cookie_domain','cookie_secure','sess_time_to_update','time_reference','cookie_prefix','encryption_key') as $key)
??{
???$this->$key = (isset($params[$key])) ? $params[$key] : $this->CI->config->item($key);
??}
??????????????? //必须设置encryption_key
??if ($this->encryption_key == '')
??{
???show_error('In order to use the Session class you are required to set an encryption key in your config file.');
??}
??// 加载string helper函数
??$this->CI->load->helper('string');
??// D如果对cookie进行加密,则引入加密类
??if ($this->sess_encrypt_cookie == TRUE)
??{
???$this->CI->load->library('encrypt');
??}
??// 如果session计入数据库,则引入db
??if ($this->sess_use_database === TRUE AND $this->sess_table_name != '')
??{
???$this->CI->load->database();
??}
??// 获取当前时间
??$this->now = $this->_get_time();
??// 如果没有设置session的有效时间,默认两年
??if ($this->sess_expiration == 0)
??{
???$this->sess_expiration = (60*60*24*365*2);
??}
??// 获取cookie名称
??$this->sess_cookie_name = $this->cookie_prefix.$this->sess_cookie_name;
??// 如果session不存在,创建新会话
??if ( ! $this->sess_read())
??{
???$this->sess_create();
??}
??else
??{
???$this->sess_update();
??}
??// 闪出标记old的闪出数据
??$this->_flashdata_sweep();
??????????????? //将新的闪出数据标记成old 标记成old的数据的数据将会在下次哀求时闪出
??$this->_flashdata_mark();
??//回收/删除 过期的session
??$this->_sess_gc();
??log_message('debug',"Session routines successfully run");
?}
?// --------------------------------------------------------------------
?/**
? * 读取session数据
? */
?function sess_read()
?{
??// 获取session
??$session = $this->CI->input->cookie($this->sess_cookie_name);
??// 没有session? 拜拜
??if ($session === FALSE)
??{
???log_message('debug','A session cookie was not found.');
???return FALSE;
??}
??// 如果加密了cookie
??if ($this->sess_encrypt_cookie == TRUE)
??{
???$session = $this->CI->encrypt->decode($session);
??}
??else
??{
???// encryption was not used,so we need to check the md5 hash
???$hash? = substr($session,strlen($session)-32); // get last 32 chars
???$session = substr($session,strlen($session)-32);
???// Does the md5 hash match?? This is to prevent manipulation of session data in userspace
???if ($hash !==? md5($session.$this->encryption_key))
???{
????log_message('error','The session cookie data did not match what was expected. This could be a possible hacking attempt.');
????$this->sess_destroy();
????return FALSE;
???}
??}
??// 反序列化存入cookie的session数组
??$session = $this->_unserialize($session);
??// 检测session的数据
??if ( ! is_array($session) OR ! isset($session['session_id']) OR ! isset($session['ip_address']) OR ! isset($session['user_agent']) OR ! isset($session['last_activity']))
??{
???$this->sess_destroy();
???return FALSE;
??}
??// session数据过期了吗
??if (($session['last_activity'] + $this->sess_expiration) < $this->now)
??{
???$this->sess_destroy();
???return FALSE;
??}
??// 是否是根据用户ip来读取session数据
??if ($this->sess_match_ip == TRUE AND $session['ip_address'] != $this->CI->input->ip_address())
??{
???$this->sess_destroy();
???return FALSE;
??}
??// 是否根据ua来匹配session数据
??if ($this->sess_match_useragent == TRUE AND trim($session['user_agent']) != trim(substr($this->CI->input->user_agent(),120)))
??{
???$this->sess_destroy();
???return FALSE;
??}
??// 如果session入库了,这种方式应该更安全点,当然负载大时,就不建议了,数据库读写压力大
??if ($this->sess_use_database === TRUE)
??{
???$this->CI->db->where('session_id',$session['session_id']);
???if ($this->sess_match_ip == TRUE)
???{
????$this->CI->db->where('ip_address',$session['ip_address']);
???}
???if ($this->sess_match_useragent == TRUE)
???{
????$this->CI->db->where('user_agent',$session['user_agent']);
???}
???$query = $this->CI->db->get($this->sess_table_name);
???// No result?? Kill it!
???if ($query->num_rows() == 0)
???{
????$this->sess_destroy();
????return FALSE;
???}
???// Is there custom data?? If so,add it to the main session array
???$row = $query->row();
???if (isset($row->user_data) AND $row->user_data != '')
???{
????$custom_data = $this->_unserialize($row->user_data);
????if (is_array($custom_data))
????{
?????foreach ($custom_data as $key => $val)
?????{
??????$session[$key] = $val;
?????}
????}
???}
??}
??// Session is valid!
??$this->userdata = $session;
??unset($session);
??return TRUE;
?}
?// --------------------------------------------------------------------
?/**
? * 将读取的session数据写入
? */
?function sess_write()
?{
??// 是否写入db
??if ($this->sess_use_database === FALSE)
??{
???$this->_set_cookie();
???return;
??}
??// set the custom userdata,the session data we will set in a second
??$custom_userdata = $this->userdata;
??$cookie_userdata = array();
??// Before continuing,we need to determine if there is any custom data to deal with.
??// Let's determine this by removing the default indexes to see if there's anything left in the array
??// and set the session data while we're at it
??foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
??{
???unset($custom_userdata[$val]);
???$cookie_userdata[$val] = $this->userdata[$val];
??}
??// Did we find any custom data?? If not,we turn the empty array into a string
??// since there's no reason to serialize and store an empty array in the DB
??if (count($custom_userdata) === 0)
??{
???$custom_userdata = '';
??}
??else
??{
???// Serialize the custom data array so we can store it
???$custom_userdata = $this->_serialize($custom_userdata);
??}
??// 更新session记录
??$this->CI->db->where('session_id',$this->userdata['session_id']);
??$this->CI->db->update($this->sess_table_name,array('last_activity' => $this->userdata['last_activity'],'user_data' => $custom_userdata));
??// Write the cookie.? Notice that we manually pass the cookie data array to the
??// _set_cookie() function. Normally that function will store $this->userdata,but
??// in this case that array contains custom data,which we do not want in the cookie.
??$this->_set_cookie($cookie_userdata);
?}
?// --------------------------------------------------------------------
?/**
? * 创建一个新的session
? */
?function sess_create()
?{
??????????????? //保证sessid 安全唯一
??$sessid = '';
??while (strlen($sessid) < 32)
??{
???$sessid .= mt_rand(0,mt_getrandmax());
??}
??$sessid .= $this->CI->input->ip_address();
??$this->userdata = array(
???????'session_id'?=> md5(uniqid($sessid,TRUE)),
???????'ip_address'?=> $this->CI->input->ip_address(),
???????'user_agent'?=> substr($this->CI->input->user_agent(),120),
???????'last_activity'?=> $this->now,
???????'user_data'??=> ''
???????);
??// Save the data to the DB if needed
??if ($this->sess_use_database === TRUE)
??{
???$this->CI->db->query($this->CI->db->insert_string($this->sess_table_name,$this->userdata));
??}
??// Write the cookie
??$this->_set_cookie();
?}
?// --------------------------------------------------------------------
?/**
? * 更新session
? */
?function sess_update()
?{
??// 默认五分钟更新
??if (($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now)
??{
???return;
??}
??// Save the old session id so we know which record to
??// update in the database if we need it
??$old_sessid = $this->userdata['session_id'];
??$new_sessid = '';
??while (strlen($new_sessid) < 32)
??{
???$new_sessid .= mt_rand(0,mt_getrandmax());
??}
??// To make the session ID even more secure we'll combine it with the user's IP
??$new_sessid .= $this->CI->input->ip_address();
??// Turn it into a hash
??$new_sessid = md5(uniqid($new_sessid,TRUE));
??// Update the session data in the session data array
??$this->userdata['session_id'] = $new_sessid;
??$this->userdata['last_activity'] = $this->now;
??// _set_cookie() will handle this for us if we aren't using database sessions
??// by pushing all userdata to the cookie.
??$cookie_data = NULL;
??// 更新数据库中几率
??if ($this->sess_use_database === TRUE)
??{
???// set cookie explicitly to only have our session data
???$cookie_data = array();
???foreach (array('session_id','last_activity') as $val)
???{
????$cookie_data[$val] = $this->userdata[$val];
???}
???$this->CI->db->query($this->CI->db->update_string($this->sess_table_name,array('last_activity' => $this->now,'session_id' => $new_sessid),array('session_id' => $old_sessid)));
??}
??// 重新写入session
??$this->_set_cookie($cookie_data);
?}
?// --------------------------------------------------------------------
?/**
? *销毁当前所有session数据
? */
?function sess_destroy()
?{
??// Kill the session DB row
??if ($this->sess_use_database === TRUE && isset($this->userdata['session_id']))
??{
???$this->CI->db->where('session_id',$this->userdata['session_id']);
???$this->CI->db->delete($this->sess_table_name);
??}
??// Kill the cookie
??setcookie(
?????$this->sess_cookie_name,
?????addslashes(serialize(array())),
?????($this->now - 31500000),
?????$this->cookie_path,
?????$this->cookie_domain,
?????0
????);
??// Kill session data
??$this->userdata = array();
?}
?// --------------------------------------------------------------------
?/**
? * 获取session数组指定元素的值
? */
?function userdata($item)
?{
??return ( ! isset($this->userdata[$item])) ? FALSE : $this->userdata[$item];
?}
?// --------------------------------------------------------------------
?/**
? * 获取所有session数据
? */
?function all_userdata()
?{
??return $this->userdata;
?}
?// --------------------------------------------------------------------
?/**
? * 添加和修改自定义的session数据
? */
?function set_userdata($newdata = array(),$newval = '')
?{
??if (is_string($newdata))
??{
???$newdata = array($newdata => $newval);
??}
??????????????? //支持数组组合方式
??if (count($newdata) > 0)
??{
???foreach ($newdata as $key => $val)
???{
????$this->userdata[$key] = $val;
???}
??}
??$this->sess_write();
?}
?// --------------------------------------------------------------------
?/**
? * 删除session数组中的元素,
? */
?function unset_userdata($newdata = array())
?{
??if (is_string($newdata))
??{
???$newdata = array($newdata => '');
??}
??if (count($newdata) > 0)
??{
???foreach ($newdata as $key => $val)
???{
????unset($this->userdata[$key]);
???}
??}
??$this->sess_write();
?}
?// ------------------------------------------------------------------------
?/**
? * Add or change flashdata,only available
? * until the next request
? *
? * @access?public
? * @param?mixed
? * @param?string
? * @return?void
? */
?function set_flashdata($newdata = array(),$newval = '')
?{
??if (is_string($newdata))
??{
???$newdata = array($newdata => $newval);
??}
??if (count($newdata) > 0)
??{
???foreach ($newdata as $key => $val)
???{
????$flashdata_key = $this->flashdata_key.':new:'.$key;
????$this->set_userdata($flashdata_key,$val);
???}
??}
?}
?// ------------------------------------------------------------------------
?/**
? * CI支持闪出数据也就是说 Session数据只对下次服务器哀求可用,有时候如果你还想在下个哀求后的哀求还有效...
???????? * keep_flashdata功能就是讲持续保持闪出数据,使其在下个哀求也有效
? */
?function keep_flashdata($key)
?{
??????????????? //将闪出数据标记成new
??$old_flashdata_key = $this->flashdata_key.':old:'.$key;
??$value = $this->userdata($old_flashdata_key);
??$new_flashdata_key = $this->flashdata_key.':new:'.$key;
??$this->set_userdata($new_flashdata_key,$value);
?}
?// ------------------------------------------------------------------------
?/**
? * 获取闪出数据
? */
?function flashdata($key)
?{
??$flashdata_key = $this->flashdata_key.':old:'.$key;
??return $this->userdata($flashdata_key);
?}
?// ------------------------------------------------------------------------
?/**
? * 将闪出数据标记成old,以便_flashdata_sweep清除数据
? */
?function _flashdata_mark()
?{
??$userdata = $this->all_userdata();
??foreach ($userdata as $name => $value)
??{
???$parts = explode(':new:',$name);
???if (is_array($parts) && count($parts) === 2)
???{
????$new_name = $this->flashdata_key.':old:'.$parts[1];
????$this->set_userdata($new_name,$value);
????$this->unset_userdata($name);
???}
??}
?}
?// ------------------------------------------------------------------------
?/**
? * 将标记成old的闪出数据闪出
? */
?function _flashdata_sweep()
?{
??$userdata = $this->all_userdata();
??foreach ($userdata as $key => $value)
??{
???if (strpos($key,':old:'))
???{
????$this->unset_userdata($key);
???}
??}
?}
?//获取当前时间
?function _get_time()
?{
??if (strtolower($this->time_reference) == 'gmt')
??{
???$now = time();
???$time = mktime(gmdate("H",$now),gmdate("i",gmdate("s",gmdate("m",gmdate("d",gmdate("Y",$now));
??}
??else
??{
???$time = time();
??}
??return $time;
?}
?// --------------------------------------------------------------------
?/**
? * 写入session cookie
? *
? */
?function _set_cookie($cookie_data = NULL)
?{
??if (is_null($cookie_data))
??{
???$cookie_data = $this->userdata;
??}
??// 序列化数组
??$cookie_data = $this->_serialize($cookie_data);
??????????????? //加密数据
??if ($this->sess_encrypt_cookie == TRUE)
??{
???$cookie_data = $this->CI->encrypt->encode($cookie_data);
??}
??else
??{
???// if encryption is not used,we provide an md5 hash to prevent userside tampering
???$cookie_data = $cookie_data.md5($cookie_data.$this->encryption_key);
??}
??????????????? //sess_expire_on_close为TRUE则,浏览器关闭,session失效
??$expire = ($this->sess_expire_on_close === TRUE) ? 0 : $this->sess_expiration + time();
??// Set the cookie
??setcookie(
?????$this->sess_cookie_name,
?????$cookie_data,
?????$expire,
?????$this->cookie_secure
????);
?}
?// --------------------------------------------------------------------
?/**
? * 序列化数组
? */
?function _serialize($data)
?{
??if (is_array($data))
??{
???foreach ($data as $key => $val)
???{
????if (is_string($val))
????{
?????$data[$key] = str_replace('','{{slash}}',$val);
????}
???}
??}
??else
??{
???if (is_string($data))
???{
????$data = str_replace('',$data);
???}
??}
??return serialize($data);
?}
?// --------------------------------------------------------------------
?/**
? * 反序列化数组
? */
?function _unserialize($data)
?{
??$data = @unserialize(strip_slashes($data));
??if (is_array($data))
??{
???foreach ($data as $key => $val)
???{
????if (is_string($val))
????{
?????$data[$key] = str_replace('{{slash}}','',$val);
????}
???}
???return $data;
??}
??return (is_string($data)) ? str_replace('{{slash}}',$data) : $data;
?}
?// --------------------------------------------------------------------
?/**
? * 回收/删除数据库中失效的session信息
? */
?function _sess_gc()
?{
??if ($this->sess_use_database != TRUE)
??{
???return;
??}
??srand(time());
??if ((rand() % 100) < $this->gc_probability)
??{
???$expire = $this->now - $this->sess_expiration;
???$this->CI->db->where("last_activity < {$expire}");
???$this->CI->db->delete($this->sess_table_name);
???log_message('debug','Session garbage collection performed.');
??}
?}
}

欢迎参与《PHP实例:CI框架Session.php源码分析》讨论,分享您的想法,编程之家 52php.cn为您提供专业教程。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读