Zend Framework 的 Zend_Session_Namespace 提供命名空間隔離、過期時間控制、跳數限制等進階功能,解決傳統 $_SESSION 管理混亂、安全性不足的問題。
不同模組使用獨立命名空間,避免鍵名衝突:
<?php
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Session_Namespace');
// 建立資料庫設定專用命名空間
$dbSession = new Zend_Session_Namespace('DbConfig');
$dbSession->host = '127.0.0.1';
$dbSession->username = 'root';
$dbSession->password = '111';
$dbSession->dbname = 'test';
// 另一模組使用不同命名空間
$userSession = new Zend_Session_Namespace('UserAuth');
$userSession->userId = 12345;
$userSession->roles = ['admin', 'editor'];
// 存取時自動隔離
echo $dbSession->host; // '127.0.0.1'
echo $userSession->userId; // 12345
?>
<?php
$session = new Zend_Session_Namespace('TempData');
// 整個命名空間 300 秒 (5 分鐘) 後過期
$session->setExpirationSeconds(300);
// 單一鍵值 60 秒過期
$session->setExpirationSeconds(60, 'captcha_code');
?>
限制變數存活的「請求跳數」,極適合一次性 Token、驗證碼:
<?php
$session = new Zend_Session_Namespace('Security');
// 變數 'csrf_token' 在 1 次請求後過期 (即讀取即失效)
$session->setExpirationHops(1, 'csrf_token');
// 變數 'login_redirect' 在 2 次請求後過期
$session->setExpirationHops(2, 'login_redirect');
// 批次設定不同跳數
$session->setExpirationHops(2, 'host');
$session->setExpirationHops(3, 'username');
$session->setExpirationHops(4, 'password');
$session->setExpirationHops(5, 'dbname');
?>
<?php
$session = new Zend_Session_Namespace('Payment');
// 支付 Token:5 分鐘或 1 次跳數,以先到者為準
$session->setExpirationSeconds(300, 'payment_token');
$session->setExpirationHops(1, 'payment_token');
// 使用時檢查
if (!isset($session->payment_token)) {
throw new Exception('支付 Token 已失效,請重新發起');
}
?>
<?php
// application/Bootstrap.php
protected function _initSession() {
Zend_Session::start([
'save_path' => APPLICATION_PATH . '/../data/session',
'use_only_cookies' => true,
'cookie_httponly' => true,
'cookie_secure' => isset($_SERVER['HTTPS']), // HTTPS 時啟用
'gc_maxlifetime' => 1440, // 24 分鐘 GC
'remember_me_seconds' => 86400 * 30 // 記住我 30 天
]);
// 註冊關閉函數確保寫入
register_shutdown_function('session_write_close');
}
?>
Zend_Session::regenerateId() 防止 Session Fixationsession.cookie_samesite = Strict 防 CSRF<?php
class SessionManager {
private $namespace;
public function __construct($namespace = 'Default') {
$this->namespace = new Zend_Session_Namespace($namespace);
}
public function set($key, $value, $ttl = null, $hops = null) {
$this->namespace->$key = $value;
if ($ttl) $this->namespace->setExpirationSeconds($ttl, $key);
if ($hops) $this->namespace->setExpirationHops($hops, $key);
}
public function get($key, $default = null) {
return $this->namespace->$key ?? $default;
}
public function has($key) {
return isset($this->namespace->$key);
}
public function remove($key) {
unset($this->namespace->$key);
}
public function clear() {
$this->namespace->unsetAll();
}
public function lock($key) {
$this->namespace->lock($key); // 防止並發修改
}
public function unlock($key) {
$this->namespace->unlock($key);
}
}
?>
<?php
// 檢視 Session 狀態
$session = new Zend_Session_Namespace('Test');
$session->foo = 'bar';
echo '命名空間: ' . $session->getNamespace() . '<br>';
echo 'Session ID: ' . Zend_Session::getId() . '<br>';
echo '是否啟動: ' . (Zend_Session::isStarted() ? '是' : '否') . '<br>';
// 迭代所有變數
foreach ($session as $key => $value) {
echo "{$key} = {$value}<br>";
}
// 取得過期資訊 (需反射存取受保護屬性)
$reflection = new ReflectionClass($session);
$expiration = $reflection->getProperty('_expirationSeconds');
$expiration->setAccessible(true);
print_r($expiration->getValue($session));
?>
掌握 Zend_Session_Namespace 的命名空間隔離與多層過期機制,能建構安全、清晰、可維護的 Session 管理體系。