直接上代码:
const TYPE_INT = 1;
const TYPE_STR = 2;
/**
* Database configration
*
* @var array
*/
private $_config = array(
‘host\' => \'127.0.0.1′,
‘port\' => 3306,
‘username\' => ‘root\',
‘password\' => ‘root\',
‘dbname\' => ‘db_mylab\',
‘tablename\' => ‘t_sessions\',
‘cookie_prefix\' => ‘mylab_\',
‘cookiepath\' => ‘/\',
‘cookiedomain\' => ”,
‘cookie_timeout\' => 900
);
/**
* Table fields type array
*
* @var array
*/
private $_db_fields = array(
‘crc32sid\' => self::TYPE_INT,
‘sessionhash\' => self::TYPE_STR,
‘idhash\' => self::TYPE_STR,
‘userid\' => self::TYPE_INT,
‘ipaddress\' => self::TYPE_STR,
‘lastactivity\' => self::TYPE_STR,
‘location\' => self::TYPE_STR,
‘loggedin\' => self::TYPE_INT,
‘heartbeat\' => self::TYPE_STR
);
/**
* db obj
*
* @var mysqli object
*/
private $_mysqli = null;
/**
* Weather the session was created or existed previously
*
* @var bool
*/
private $_created = false;
/**
* Array of changes.
*
* @var array
*/
private $_changes = array();
/**
* @var bool
*/
private $_db_inited = false;
/**
* session host
*
* @var string
*/
private $_session_host = ”;
/**
* session idhash
*
* @var string
*/
private $_session_idhash = ”;
private $_dbsessionhash = ”;
private $_vars = array();
public function __construct()
{
$this->_dbsessionhash = addslashes($this->get_cookie(‘sessionhash\'));
$this->_session_host = substr($_SERVER[‘REMOTE_ADDR\'], 0, 15);
#This should *never* change during a session
$this->_session_idhash = md5($_SERVER[‘HTTP_USER_AGENT\'] . self::fetch_substr_ip(self::fetch_alt_ip()) );
$this->_init_config();
$this->init_db();
$gotsession = false;
if ($this->_dbsessionhash)
{
$sql = ‘
SELECT *
FROM ‘ . $this->_config[‘tablename\'] . ‘
WHERE crc32sid = ‘ . sprintf(‘%u\', crc32($this->_dbsessionhash)) . ‘
AND sessionhash = \'‘ . $this->_dbsessionhash . ‘\'
AND idhash = \'‘ . $this->_session_idhash . ‘\'
AND heartbeat > \'‘ . date(‘Y-m-d H:i:s\' ,TIMENOW – $this->_config[‘cookie_timeout\']) . ‘\'‘;
//echo $sql;exit;
$result = $this->_mysqli->query($sql);
$session = $result->fetch_array(MYSQLI_ASSOC);
if ($session AND ($this->fetch_substr_ip($session[‘ipaddress\']) == $this->fetch_substr_ip($this->_session_host)))
{
$gotsession = true;
$this->_vars = $session;
$this->_created = false;
}
}
if ($gotsession == false)
{
$this->_vars = $this->fetch_session();
$this->_created = true;
$gotsession = true;
}
if ($this->_created == false)
{
$this->set(‘lastactivity\', date(‘Y-m-d H:i:s\', TIMENOW));
$this->set(‘location\', $_SERVER[‘REQUEST_URI\']);
}
}
/**
* Builds an array that can be used to build a query to insert/update the session
*
* @return array Array of column name => prepared value
*/
private function _build_query_array()
{
$return = array();
foreach ($this->_db_fields AS $fieldname => $cleantype)
{
switch ($cleantype)
{
case self::TYPE_INT:
$cleaned = is_numeric($this->_vars[\"$fieldname\"]) ? $this->_vars[\"$fieldname\"] : intval($this->_vars[\"$fieldname\"]);
break;
case self::TYPE_STR:
default:
$cleaned = \"\'\" . addslashes($this->_vars[\"$fieldname\"]) . \"\'\";
}
$return[\"$fieldname\"] = $cleaned;
}
return $return;
}
/**
* Sets a session variable and updates the change list.
*
* @param string Name of session variable to update
* @param string Value to update it with
*/
public function set($key, $value)
{
if ($this->_vars[\"$key\"] != $value)
{
$this->_vars[\"$key\"] = $value;
$this->_changes[\"$key\"] = true;
}
}
public function get($key)
{
return $this->_vars[\"$key\"];
}
public function unsetchangedvar($var)
{
if (isset($this->_changes[\"$var\"]))
{
unset($this->_changes[\"$var\"]);
}
}
/**
* Fetches a valid sessionhash value, not necessarily the one tied to this session.
*
* @return string 32-character sessionhash
*/
static function fetch_sessionhash()
{
return hash(‘md5′ , TIMENOW . rand(1, 100000) . uniqid() );
}
private function _init_config()
{
$registry = Zend_Registry::getInstance();
$config = $registry->get(‘config\');
$this->_config[‘host\'] = $config->database->params->host;
$this->_config[‘port\'] = $config->database->params->port;
$this->_config[‘username\'] = $config->database->params->username;
$this->_config[‘password\'] = $config->database->params->password;
$this->_config[‘dbname\'] = $config->database->params->dbname;
$this->_config[‘tablename\'] = $config->database->session->tablename;
}
/**
* initialize database connection
*/
public function init_db()
{
if ($this->_db_inited)
{
return true;
}
//mysqli_report(MYSQLI_REPORT_OFF);
$this->_mysqli = new mysqli(
$this->_config[‘host\'],
$this->_config[‘username\'],
$this->_config[‘password\'],
$this->_config[‘dbname\'],
$this->_config[‘port\']
);
/* check connection */
if (mysqli_connect_errno())
{
// printf(\"Connect failed: %sn\", mysqli_connect_error());
// echo ‘in ‘, __FILE__, ‘ on line ‘, __LINE__;
echo \"{ success: false, errors: { reason: ‘ Connect failed: \" . addslashes( mysqli_connect_error() ) . \"\' }}\";
exit();
}
$this->_mysqli->query(‘set names latin1′);
$this->_db_inited = true;
return true;
}
/**
* Fetches an alternate IP address of the current visitor, attempting to detect proxies etc.
*
* @return string
*/
static function fetch_alt_ip()
{
$alt_ip = $_SERVER[‘REMOTE_ADDR\'];
if (isset($_SERVER[‘HTTP_CLIENT_IP\']))
{
$alt_ip = $_SERVER[‘HTTP_CLIENT_IP\'];
}
else if (isset($_SERVER[‘HTTP_FROM\']))
{
$alt_ip = $_SERVER[‘HTTP_FROM\'];
}
return $alt_ip;
}
/**
* Returns the IP address with the specified number of octets removed
*
* @param string IP address
*
* @return string truncated IP address
*/
static function fetch_substr_ip($ip, $length = null)
{
return implode(‘.\', array_slice(explode(‘.\', $ip), 0, 4 – $length));
}
/**
* Fetches a default session. Used when creating a new session.
*
* @param integer User ID the session should be for
*
* @return array Array of session variables
*/
public function fetch_session($userid = 0)
{
$sessionhash = self::fetch_sessionhash();
$this->set_cookie(‘sessionhash\', $sessionhash);
return array(
‘crc32sid\' => sprintf(‘%u\', crc32($sessionhash)),
‘sessionhash\' => $sessionhash,
‘idhash\' => $this->_session_idhash,
‘userid\' => $userid,
‘ipaddress\' => $this->_session_host,
‘lastactivity\' => date(‘Y-m-d H:i:s\', TIMENOW),
‘location\' => $_SERVER[‘REQUEST_URI\'],
‘loggedin\' => $userid ? 1 : 0,
‘heartbeat\' => date(‘Y-m-d H:i:s\', TIMENOW)
);
}
public function get_cookie($cookiename)
{
$full_cookiename = $this->_config[‘cookie_prefix\'] . $cookiename;
if (isset($_COOKIE[$full_cookiename]))
{
return $_COOKIE[$full_cookiename];
}
else
{
return false;
}
}
public function set_cookie($name, $value = ”, $permanent = 1, $allowsecure = true)
{
if ($permanent)
{
$expire = TIMENOW + 60 * 60 * 24 * 365;
}
else
{
$expire = 0;
}
if ($_SERVER[‘SERVER_PORT\'] == \'443′)
{
// we\'re using SSL
$secure = 1;
}
else
{
$secure = 0;
}
// check for SSL
$secure = ((REQ_PROTOCOL === ‘https\' AND $allowsecure) ? true : false);
$name = $this->_config[‘cookie_prefix\'] . $name;
$filename = ‘N/A\';
$linenum = 0;
if (!headers_sent($filename, $linenum))
{ // consider showing an error message if there not sent using above variables?
if ($value == ” AND strlen($this->_config[‘cookiepath\']) > 1 AND strpos($this->_config[‘cookiepath\'], ‘/\') !== false)
{
// this will attempt to unset the cookie at each directory up the path.
// ie, cookiepath = /test/abc/. These will be unset: /, /test, /test/, /test/abc, /test/abc/
// This should hopefully prevent cookie conflicts when the cookie path is changed.
$dirarray = explode(‘/\', preg_replace(‘#/+$#\', ”, $this->_config[‘cookiepath\']));
$alldirs = ”;
foreach ($dirarray AS $thisdir)
{
$alldirs .= \"$thisdir\";
if (!empty($thisdir))
{ // try unsetting without the / at the end
setcookie($name, $value, $expire, $alldirs, $this->_config[‘cookiedomain\'], $secure);
}
$alldirs .= \"/\";
setcookie($name, $value, $expire, $alldirs, $this->_config[‘cookiedomain\'], $secure);
}
}
else
{
setcookie($name, $value, $expire, $this->_config[‘cookiepath\'], $this->_config[‘cookiedomain\'], $secure);
}
}
else if (!DEBUG)
{
echo \"can\'t set cookies\";
}
}
private function _save()
{
$cleaned = $this->_build_query_array();
if ($this->_created)
{
//var_dump($cleaned);
# insert query
$this->_mysqli->query(‘
INSERT IGNORE INTO ‘ . $this->_config[‘tablename\'] . ‘
(‘ . implode(‘,\', array_keys($cleaned)) . ‘)
VALUES
(‘ . implode(‘,\', $cleaned). ‘)
‘);
}
else
{
# update query
$update = array();
foreach ($cleaned AS $key => $value)
{
if (!empty($this->_changes[\"$key\"]))
{
$update[] = \"$key = $value\";
}
}
if (sizeof($update) > 0)
{
$sql = ‘UPDATE ‘ . $this->_config[‘tablename\'] . ‘
SET ‘ . implode(‘, ‘, $update) . ‘
WHERE crc32sid = ‘ . sprintf(‘%u\', crc32($this->_dbsessionhash)) . ‘
AND sessionhash = \'‘ . $this->_dbsessionhash . ‘\'‘;
//echo $sql;
$this->_mysqli->query($sql);
}
}
}
public function getOnlineUserNum()
{
$sql = ‘
SELECT count(*) as cnt
FROM ‘ . $this->_config[‘tablename\'] . ‘
WHERE loggedin = 1
AND heartbeat > \'‘ . date(‘Y-m-d H:i:s\' ,TIMENOW – $this->_config[‘cookie_timeout\']) . ‘\'‘;
$result = $this->_mysqli->query($sql);
$row = $result->fetch_array(MYSQLI_ASSOC);
return $row[‘cnt\'];
}
private function _gc()
{
$rand_num = rand(); # randow integer between 0 and getrandmax()
if ($rand_num < 100)
{
$sql = ‘DELETE FROM ‘ . $this->_config[‘tablename\'] . ‘
WHERE heartbeat < \'‘ . date(‘Y-m-d H:i:s\' ,TIMENOW – $this->_config[‘cookie_timeout\']) . ‘\'‘;
$this->_mysqli->query($sql);
}
}
public function __destruct()
{
$this->_save();
$this->_gc();
$this->_mysqli->close();
}
}
本文地址:https://www.stayed.cn/item/2090
转载请注明出处。
本站部分内容来源于网络,如侵犯到您的权益,请 联系我