string session_id([string $id])
session_id() 返回當前會話 ID,無會話時返回空字符串session_id('custom_id') 必須在 session_start() 之前調用session_name=session_id 字符串,用於 URL 透傳// 獲取
session_start();
echo session_id(); // 輸出類似: 08nr1fav9jqs2pdi5qlpsmd247
// 設置自定義 ID(罕見場景:跨域共享、測試)
session_id('my_custom_session_123');
session_start();
echo session_id(); // 輸出: my_custom_session_123
PHP 5.3.6 參考:ext/session/session.c 第 345 行 php_session_create_id()
php_combined_lcg() (線性同餘) + gettimeofday() 微秒 + getpid() 進程 ID + zend_getenv() 環境變量session.hash_function (默認 MD5 / 可選 SHA-1) 計算摘要session.hash_bits_per_character (默認 4 → 十六進制) 轉換為字符串| ini 設置 | 默認值 | 影響 |
|---|---|---|
| session.hash_function | 0 (MD5) | 0=MD5(128bit), 1=SHA-1(160bit) |
| session.hash_bits_per_character | 4 | 4=0-9a-f(16進制), 5=0-9a-v(32進制), 6=0-9a-zA-Z,- (64進制) |
| session.sid_length | 32 (PHP 7.1+) | Session ID 最小長度,舊版本由上兩項決定 |
PHP 5.4.6 默認配置 (MD5 + 4 bits/char) 產生的 ID:
sess_00nrqa20hjrlaiac0eu726i4q5 (26 字符) sess_89j9ifuqrbplk0rti2va2k1ha0 sess_g2rv1kd6ijsj6g6c9jq5mqglv5 ...
sess_[0-9a-f] 十六進制小寫ini_set('session.sid_length', 48); // 更長更安全
ini_set('session.sid_bits_per_character', 6); // 64 進制:A-Z a-z 0-9 , -
session_start();
// 產生 48 字符,字符集更大,熵值顯著提升
用戶首次訪問
│
▼
PHP 生成 Session ID (php_session_create_id)
│
▼
設置 Set-Cookie: PHPSESSID=abc123... (默認名稱)
│
▼
創建存儲文件: /tmp/sess_abc123... (文件處理器)
│
▼
後續請求攜帶 Cookie
│
▼
PHP 讀取 Cookie → session_id() → 定位存儲 → 反序列化 $_SESSION
│
▼
腳本結束 → 序列化 $_SESSION → 寫回存儲
| 風險 | 原理 | 防護措施 |
|---|---|---|
| Session Fixation | 攻擊者強制受害者使用已知 SID | session_regenerate_id(true) 登錄後重新生成 |
| Session Hijacking | 竊取 Cookie (XSS/中間人/側信道) | HTTPS + HttpOnly + Secure + SameSite=Strict |
| Session Prediction | 預測/暴力破解 SID | 增大 sid_length、使用 64 進制、啟用 strict 模式 |
| Session Injection | 注入惡意數據到 $_SESSION | 不可信數據不直接存入 Session、簽名驗證 |
// 必須項
ini_set('session.use_strict_mode', '1'); // 拒絕未初始化的 SID (PHP 5.5+)
ini_set('session.use_cookies', '1'); // 僅用 Cookie 傳遞
ini_set('session.use_only_cookies', '1'); // 禁用 URL 透傳
ini_set('session.cookie_httponly', '1'); // JS 不可讀
ini_set('session.cookie_secure', '1'); // 僅 HTTPS (需 HTTPS 環境)
ini_set('session.cookie_samesite', 'Strict'); // CSRF 防護 (PHP 7.3+)
// 推薦項
ini_set('session.gc_maxlifetime', '1800'); // 30 分鐘過期
ini_set('session.gc_probability', '1');
ini_set('session.gc_divisor', '100'); // 1% 概率啟動 GC
ini_set('session.sid_length', '48'); // PHP 7.1+
ini_set('session.sid_bits_per_character', '6');
// 代碼層面
session_start();
// 關鍵操作後(登錄、提權、支付)重新生成 ID
if ($loginSuccess) session_regenerate_id(true);
| 方案 | 原理 | 優點 | 缺點 |
|---|---|---|---|
| 文件共享 (NFS/GlusterFS) | 共享存儲掛載 | 零代碼改動 | 單點故障、性能瓶頸、鎖競爭 |
| 數據庫存儲 | 自定義 save_handler 寫 MySQL | 持久化、可查詢 | 寫入延遲、連接池壓力 |
| Redis/Memcached | 內存 KV 存儲,TTL 自動過期 | 高性能、原子操作、集群擴展 | 數據易失、需持久化配置 |
| JWT 無狀態 | 客戶端攜帶簽名 Token | 無服務端存儲、水平擴展極簡 | 無法撤銷、體積大、續簽複雜 |
class RedisSessionHandler implements SessionHandlerInterface {
private $redis, $prefix = 'sess:', $ttl = 1800;
public function __construct(Redis $redis) { $this->redis = $redis; }
public function open($savePath, $sessionName) { return true; }
public function close() { return true; }
public function read($id) {
$data = $this->redis->get($this->prefix . $id);
return $data ?: '';
}
public function write($id, $data) {
return $this->redis->setex($this->prefix . $id, $this->ttl, $data);
}
public function destroy($id) {
return $this->redis->del($this->prefix . $id);
}
public function gc($maxlifetime) { return true; } // Redis TTL 自動清理
}
// 註冊
$handler = new RedisSessionHandler(new Redis());
session_set_save_handler($handler, true);
session_start();
session_id() 雖是簡單函數,背後涉及熵源收集、哈希編碼、存儲協議、安全策略等核心機制。現代 PHP 應用建議:配置高熵 ID、啟用嚴格模式、HTTPS 全站、Redis 分佈式存儲、關鍵節點重新生成 ID。理解其原理,才能構建經得起攻擊的會話系統。