Files
wy/ZeedFramework/library/Zeed/Session.php

398 lines
13 KiB
PHP
Raw Normal View History

2026-01-07 11:40:41 +08:00
<?php
/**
* Zeed Platform Project
* Based on Zeed Framework & Zend Framework.
*
* BTS - Billing Transaction Service
* CAS - Central Authentication Service
*
* LICENSE
* http://www.zeed.com.cn/license/
*
* @category Zeed
* @package Zeed_Session
* @copyright Copyright (c) 2010 Zeed Technologies PRC Inc. (http://www.zeed.com.cn)
* @author Zeed Team (http://blog.zeed.com.cn)
* @since 2010-6-30
* @version SVN: $Id: Session.php 10460 2011-06-07 05:35:51Z xsharp $
*/
defined('SESSION_NAME') || define('SESSION_NAME', 'ZEED_SESSION');
class Zeed_Session
{
private static $_sessionid;
private static $_sessionStarted = false;
private static $_writeClosed = false;
private static $_destroyed = false;
private static $_sessionCookieDeleted = false;
/**
* Whether or not the session id has been regenerated this request.
*
* Id regeneration state
* <0 - regenerate requested when session is started
* 0 - do nothing
* >0 - already called session_regenerate_id()
*
* @var int
*/
private static $_regenerateIdState = 0;
/**
* Private list of php's ini values for ext/session
* null values will default to the php.ini value, otherwise
* the value below will overwrite the default ini value, unless
* the user has set an option explicity with setOptions()
*
* @var array
*/
private static $_defaultOptions = array(
'save_path' => null,
'name' => null, /* this should be set to a unique value for each application */
'save_handler' => null,
//'auto_start' => null, /* intentionally excluded (see manual) */
'gc_probability' => null,
'gc_divisor' => null,
'gc_maxlifetime' => null,
'serialize_handler' => null,
'cookie_lifetime' => null,
'cookie_path' => null,
'cookie_domain' => null,
'cookie_secure' => null,
'cookie_httponly' => null,
'use_cookies' => null,
'use_only_cookies' => 'on',
'referer_check' => null,
'entropy_file' => null,
'entropy_length' => null,
'cache_limiter' => null,
'cache_expire' => null,
'use_trans_sid' => null,
'bug_compat_42' => null,
'bug_compat_warn' => null,
'hash_function' => null,
'hash_bits_per_character' => null);
/**
* List of options pertaining to Zend_Session that can be set by developers
* using Zeed_Session::setOptions(). This list intentionally duplicates
* the individual declaration of static "class" variables by the same names.
*
* @var array
*/
private static $_localOptions = array(
'use_uuid_for_sid' => '_useUUIDForSID');
/**
* 是否使用 UUID 作为 Session ID
*/
private static $_useUUIDForSID = true;
/**
* 默认设置是否已设置标记
* Whether the default options listed in Zend_Session::$_localOptions have been set
*
* @var bool
*/
private static $_defaultOptionsSet = false;
/**
* @var Zeed_Session_Storage_Interface
*/
private static $_storager = null;
/**
* Session Save Handler assignment
*
* @param Zeed_Session_Storage_Interface $interface
* @return void
*/
public static function setStorager(Zeed_Session_Storage_Interface $storager)
{
self::$_storager = $storager;
session_set_save_handler(array(
&$storager,
'open'), array(
&$storager,
'close'), array(
&$storager,
'read'), array(
&$storager,
'write'), array(
&$storager,
'destroy'), array(
&$storager,
'gc'));
}
public static function getStorager()
{
return self::$_storager;
}
/**
* 重新生成 Session ID这意味了 Session 的数据将初始化
* 建议在 Session 启动后再调用该函数
*
* @throws Zeed_Exception
* @return void
*/
public static function regenerateId($deleteOldSession = true)
{
if (! self::$_sessionStarted) {
if (headers_sent($filename, $linenum)) {
throw new Zeed_Exception("You must call " . __CLASS__ . '::' . __FUNCTION__ . "() before any output has been sent to the browser; output started in {$filename}/{$linenum}");
}
}
if (self::$_sessionStarted && self::$_regenerateIdState <= 0) {
session_regenerate_id($deleteOldSession);
self::$_regenerateIdState = 1;
} else {
self::$_regenerateIdState = - 1;
}
}
/**
* 启动 Session
*
* @param bool|array $options OPTIONAL Either user supplied options, or flag indicating if start initiated automatically
* @throws Zend_Session_Exception
* @return void
*/
public static function start($options = false)
{
if (self::$_sessionStarted && self::$_destroyed) {
throw new Zeed_Exception('The session was explicitly destroyed during this request, attempting to re-start is not allowed.');
}
if (self::$_sessionStarted) {
return; // already started
}
$filename = $linenum = null;
if (headers_sent($filename, $linenum)) {
throw new Zeed_Exception("Session must be started before any output has been sent to the browser;" . " output started in {$filename}/{$linenum}");
}
// See http://www.php.net/manual/en/ref.session.php for explanation
if (defined('SID')) {
throw new Zeed_Exception('session has already been started by session.auto-start or session_start()');
}
$startedCleanly = session_start();
self::$_sessionStarted = true;
if (self::$_regenerateIdState === - 1) {
self::regenerateId();
}
}
/**
* 获取当前 Session ID
* session_id() returns the session id for the current session or the empty string ("")
* if there is no current session (no current session id exists).
*
* @return string
*/
public static function getID()
{
return session_id();
}
/**
* Session 设置
*
* @param array $userOptions - pass-by-keyword style array of <option name, option value> pairs
* @throws Zend_Session_Exception
* @return void
*/
public static function setOptions(array $userOptions = array(), $throwException = true)
{
// set default options on first run only (before applying user settings)
if (! self::$_defaultOptionsSet) {
foreach (self::$_defaultOptions as $defaultOptionName => $defaultOptionValue) {
if (isset(self::$_defaultOptions[$defaultOptionName])) {
ini_set("session.$defaultOptionName", $defaultOptionValue);
}
}
self::$_defaultOptionsSet = true;
}
// set the options the user has requested to set
foreach ($userOptions as $userOptionName => $userOptionValue) {
$userOptionName = strtolower($userOptionName);
// set the ini based values
2026-01-09 15:18:26 +08:00
// 如果session已经启动跳过ini_set以避免警告
2026-01-07 11:40:41 +08:00
if (array_key_exists($userOptionName, self::$_defaultOptions)) {
2026-01-09 15:18:26 +08:00
if (!self::$_sessionStarted && session_status() !== PHP_SESSION_ACTIVE) {
@ini_set("session.$userOptionName", $userOptionValue);
}
2026-01-07 11:40:41 +08:00
} elseif (isset(self::$_localOptions[$userOptionName])) {
self::${self::$_localOptions[$userOptionName]} = $userOptionValue;
}
if ($throwException) {
throw new Zeed_Exception("Unknown option: $userOptionName = $userOptionValue");
}
}
}
/**
* 为当前用户指定一个 Session ID
*
* @param string $id
* @return void
* @throws Zeed_Exception
*/
public static function setID($id)
{
if (defined('SID')) {
throw new Zeed_Exception('The session has already been started. The session id must be set first.');
}
if (headers_sent($filename, $linenum)) {
throw new Zeed_Exception("You must call " . __CLASS__ . '::' . __FUNCTION__ . "() before any output has been sent to the browser; output started in {$filename}/{$linenum}");
}
if (! is_string($id) || $id === '') {
throw new Zeed_Exception('You must provide a non-empty string as a session identifier.');
}
session_id($id);
}
public static function getSessionid()
{
if ($_SESSION[SESSION_NAME] != '') {
self::$_sessionid = $_SESSION[SESSION_NAME];
unset($_SESSION[SESSION_NAME]);
$_SESSION[SESSION_NAME] = self::$_sessionid; // Reset
} elseif ($_COOKIE[SESSION_NAME] != '') {
self::$_sessionid = $_COOKIE[SESSION_NAME];
unset($_SESSION[SESSION_NAME]);
$_SESSION[SESSION_NAME] = self::$_sessionid; // Reset
} else {
return 0;
}
}
/**
* destroy() - This is used to destroy session data, and optionally, the session cookie itself
*
* @param bool $remove_cookie - OPTIONAL remove session id cookie, defaults to true (remove cookie)
* @return void
*/
public static function destroy($removeCookie = true)
{
if (self::$_destroyed) {
return;
}
session_destroy();
self::$_destroyed = true;
if ($removeCookie) {
self::expireSessionCookie();
}
2026-01-09 15:18:26 +08:00
}
/**
* 清除SESSION
*/
public static function unsetSession ($session_name)
{
unset($_SESSION[$session_name]);
2026-01-07 11:40:41 +08:00
}
/**
* expireSessionCookie() - Sends an expired session id cookie, causing the client to delete the session cookie
*
* @return void
*/
public static function expireSessionCookie()
{
if (self::$_sessionCookieDeleted) {
return;
}
self::$_sessionCookieDeleted = true;
if (isset($_COOKIE[session_name()])) {
$cookie_params = session_get_cookie_params();
// strtotime('1980-01-01'),
setcookie(session_name(), false, 315554400, $cookie_params['path'], $cookie_params['domain'], $cookie_params['secure']);
}
}
/**
* writeClose() - Shutdown the sesssion, close writing and detach $_SESSION from the back-end storage mechanism.
* This will complete the internal data transformation on this request.
*
* @return void
*/
public static function writeClose()
{
if (self::$_writeClosed) {
return;
}
session_write_close();
self::$_writeClosed = true;
}
/**
* 快速初始化SESSION, 参数可以为字符串或数组, 为字符串时自动加载配置.
*
* @param string|array $config
* @return bloean
*/
public static function instance($config = null)
{
if (is_null($config)) {
$sessionConfig = Zeed_Config::loadGroup('session');
} elseif (is_string($config)) {
$sessionConfig = Zeed_Config::loadGroup($config);
} elseif (is_array($config)) {
$sessionConfig = $config;
}
if (is_array($sessionConfig)) {
$storager = $sessionConfig['storager'];
if ($storager == 'default') {
$sessionStorager = null;
} elseif ($storager != '') {
$class = 'Zeed_Session_Storage_' . ucfirst($storager);
$sessionStorager = new $class($sessionConfig[$storager]);
} else {
throw new Zeed_Exception('No session storager defined.');
}
if (null !== $sessionStorager) {
Zeed_Session::setStorager($sessionStorager);
}
if (isset($sessionConfig[$storager]) && is_array($sessionConfig[$storager]) && count($sessionConfig[$storager])) {
Zeed_Session::setOptions($sessionConfig[$storager], false);
}
Zeed_Session::start();
return true;
}
return false;
}
}
// End ^ LF ^ UTF-8