亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > PHP > 正文

CI框架Session.php源碼分析

2024-05-04 23:26:46
字體:
來源:轉載
供稿:網友
Session類并不使用PHP本身的session,而是使用類自己的session,這樣做,可以給開發者提供更大的彈性。下面我們就來仔細分析下CI框架的Session類Session.php文件
 
 

CI的Session并不是原生的session,正是我前面所有的cookie based session,另外,CI可以根據用戶選擇配置是否將session存入數據庫中,本人很喜歡這個功能,還有就是“閃出數據”的功能,既閃出數據只是對下次服務器請求可以,之后就會被自動清除。常見使用方法有:

$this->session->set_userdata('some_name', 'some_value'); //設置session數據

$this->session->userdata('item'); //獲取session數據

$this->session->unset_userdata('some_name'); //刪除session數據

$this->session->sess_destroy(); //銷毀session數據

$this->session->set_flashdata('item', 'value'); //設置閃存數據

$this->session->flashdata('item'); //獲取閃存數據

$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, 0, 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(), 0, 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(), 0, 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','ip_address','user_agent','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", $now), gmdate("s", $now), gmdate("m", $now), gmdate("d", $now), 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_path,
     $this->cookie_domain,
     $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('//', '{{slash}}', $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.');
  }
 }
}
 

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲国产精品高清久久久| 久久久999国产精品| 91久久久久久久一区二区| 高清一区二区三区日本久| 亚洲天堂久久av| 在线激情影院一区| 国产精品99久久久久久www| 一区二区三欧美| 国产一区二区三区在线视频| 超在线视频97| 欧美一级黄色网| 亚洲电影中文字幕| 久久久久久久久91| 亚洲欧美制服综合另类| 欧美日韩一区二区免费在线观看| 欧美视频中文在线看| 日韩中文字在线| 91精品国产91久久久久久久久| 自拍偷拍亚洲区| 国产情人节一区| 欧美成人黑人xx视频免费观看| 欧美一级片在线播放| 久久天堂av综合合色| 成人免费视频在线观看超级碰| 欧美一乱一性一交一视频| 日韩免费观看高清| 精品久久久在线观看| 7m第一福利500精品视频| 日本午夜人人精品| 精品国产电影一区| 欧美在线视频播放| 欧美高清电影在线看| 91探花福利精品国产自产在线| 亚洲娇小xxxx欧美娇小| 国模私拍一区二区三区| 欧美激情喷水视频| 国产精品日韩在线一区| 国产精品自产拍在线观| 国产精品444| 日本一区二区三区在线播放| 欧美亚洲国产精品| 亚洲专区在线视频| 91精品啪在线观看麻豆免费| 亚洲一区二区福利| 久久精品亚洲精品| 亚洲国产精品久久久久| 亚洲欧美精品伊人久久| 国产成人精品视| 日韩高清av一区二区三区| 久久资源免费视频| 亚洲视频axxx| 日本精品一区二区三区在线| 麻豆一区二区在线观看| 中文字幕亚洲精品| 精品视频久久久久久久| 国产精品九九久久久久久久| 欧美亚洲在线观看| 亚洲免费成人av电影| 亚洲日本中文字幕| 91九色综合久久| 欧美一二三视频| 亚洲国语精品自产拍在线观看| 97人人模人人爽人人喊中文字| 亚洲欧美在线看| 国产精品免费久久久| 欧美一级在线播放| 日韩一区二区在线视频| 欧美精品在线看| 中文字幕免费国产精品| 狠狠操狠狠色综合网| 欧美激情亚洲国产| 日韩中文字幕久久| 国产亚洲一区二区精品| 欧美午夜无遮挡| 欧美—级a级欧美特级ar全黄| 日韩精品免费在线观看| 亚洲国产成人久久综合一区| 久久久成人的性感天堂| 欧美成aaa人片在线观看蜜臀| 中文字幕精品av| 亚洲一区二区自拍| 亚洲国产精品资源| 久久久久九九九九| 日韩中文字幕亚洲| 日韩中文字幕在线视频| 97人人爽人人喊人人模波多| 亚洲第一福利在线观看| 日韩中文字幕国产| 欧美大尺度激情区在线播放| 欧美国产日韩一区二区三区| 亚洲天堂男人天堂女人天堂| 亚洲午夜激情免费视频| 国产精品女人久久久久久| 亚洲男人第一av网站| 日韩网站免费观看高清| 自拍偷拍免费精品| 一区二区三区 在线观看视| 国产亚洲一区二区在线| 日韩欧美一区二区三区久久| 国产精品永久免费视频| 97在线视频国产| 最近2019中文字幕一页二页| 性色av一区二区三区在线观看| 欧美午夜影院在线视频| 成人免费福利在线| 久久国产精品网站| 亚洲精品视频网上网址在线观看| 久久精品久久久久电影| 久久国产精品久久久久久久久久| 国产精品视频成人| 国产精品极品在线| 97视频在线看| 一区二区三区www| 精品视频在线播放免| 亚洲国产另类 国产精品国产免费| 91久久夜色精品国产网站| 最近中文字幕日韩精品| 色偷偷偷综合中文字幕;dd| 国产亚洲精品久久| zzjj国产精品一区二区| 狠狠躁夜夜躁久久躁别揉| 97在线免费观看| 亚洲色图50p| 亚洲精品短视频| 日韩av一卡二卡| 一本大道亚洲视频| 国产精品最新在线观看| 午夜免费在线观看精品视频| 青青久久aⅴ北条麻妃| 亚洲色图15p| 欧美精品videos另类日本| 久久久久久久av| 国产一区二区日韩精品欧美精品| 欧美日韩一区二区三区在线免费观看| 国产精品视频99| 精品性高朝久久久久久久| 精品中文字幕久久久久久| 久久五月情影视| 欧美人交a欧美精品| 97涩涩爰在线观看亚洲| 亚洲电影免费在线观看| 夜夜狂射影院欧美极品| 81精品国产乱码久久久久久| 亚洲影院高清在线| 97超碰国产精品女人人人爽| 亚洲奶大毛多的老太婆| 欧美性少妇18aaaa视频| 日本免费久久高清视频| 欧美午夜精品久久久久久久| 国产精品欧美在线| 国产黑人绿帽在线第一区| 911国产网站尤物在线观看| 欧美疯狂做受xxxx高潮| 国产成人精品免费久久久久| 韩国视频理论视频久久| 欧美高清videos高潮hd| 成人性生交大片免费看视频直播| 少妇高潮久久久久久潘金莲| 国产精品丝袜久久久久久不卡| 日本中文字幕久久看| 亚洲国产美女精品久久久久∴| 国产精品亚洲第一区| 亚洲影视九九影院在线观看| 国产精品福利网站|