首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

IE 新視窗 Session 遺失問題實測與解決方案:Cookie 跨進程共享機制詳解

     編輯:PHP 綜合知識

在 IE6-IE9 中,使用 window.open() 或 target="_blank" 開啟新視窗時,PHP Session ID (PHPSESSID) 因儲存於「進程級」 Cookie(無 Expires,瀏覽器關閉即失效),導致新進程無法讀取舊進程的 Session,造成登入狀態遺失。本文詳細實測過程、根因分析與解決方案。

問題重現

<?php
// index.php
setcookie('persist_cookie', 'value', time() + 3600); // 持久性 Cookie
session_start();
$_SESSION['test'] = 'session_value';
var_dump($_SESSION, $_COOKIE);
?>
<input type="button" value="window.open" onclick="window.open('b.php');">
<a href="b.php" target="_blank">target=_blank</a>
<?php
// b.php
session_start();
var_dump($_SESSION, $_COOKIE);

實測結果對照

瀏覽器window.opentarget="_blank"持久性 CookieSession Cookie
IE6/7/8/9 (IETester)遺失遺失保留遺失
IE10/11 (Win 內建)正常正常保留保留
Chrome正常正常保留保留
Firefox正常正常保留保留

根因分析

  • Session Cookie (PHPSESSID): 無 Expires/Max-Age,屬「會話級 Cookie」,瀏覽器進程關閉即銷毀。IE6-9 開新視窗會啟動新進程,舊進程的會話級 Cookie 不共享。
  • 持久性 Cookie: 設有 Expires,寫入硬碟,跨進程可讀取。
  • Chrome/Firefox/IE10+: 採多執行緒共享 Cookie 罐,不存在此問題。

解決方案

方案一:將 PHPSESSID 設為持久性 Cookie(推薦)

<?php
// 在 session_start() 之前設定
$lifetime = 3600 * 24 * 30; // 30 天
session_set_cookie_params($lifetime, '/', '', false, true); // path, domain, secure, httponly
session_start();

// 或直接修改 php.ini
// session.cookie_lifetime = 2592000
// session.cookie_path = /
// session.cookie_httponly = 1

將 Session ID 寫入持久性 Cookie,跨進程即可共享。需注意安全性:建議啟用 httponly、HTTPS 下啟用 secure。

方案二:URL 透傳 Session ID(PHP 內建)

<?php
ini_set('session.use_trans_sid', 1);
ini_set('session.use_only_cookies', 0);
session_start();

PHP 會自動將 PHPSESSID 附加至相對連結/表單 action。缺點: 不美觀、易洩露 Session ID、相對路徑才會自動附加、靜態資源也會帶上參數。

方案三:Cookie + Session 雙重驗證(最穩健)

<?php
// 登入成功時
$user_id = 123;
$token = bin2hex(random_bytes(32));
// 存資料庫:user_sessions (user_id, token, expire, ua, ip)
setcookie('auth_token', $token, time() + 86400*30, '/', '', true, true); // 持久、httponly、secure

// 每次請求驗證
session_start();
if (empty($_SESSION['user_id']) && !empty($_COOKIE['auth_token'])) {
    // 查資料庫驗證 token,通過則重建 $_SESSION['user_id']
}

不依賴 PHP 原生 Session 機制,完全由應用層控制,跨瀏覽器、跨進程、跨裝置皆穩定。

方案四:前端避免開新視窗(業務允許時)

  • 改用 Modal/彈窗而非 window.open。
  • 若必須開新視窗,透過 URL 參數傳遞 Token:window.open('b.php?token=' + getCookie('auth_token'))。

總結建議

  1. 現代專案:方案三(自訂 Token + 持久 Cookie + 資料庫驗證)最穩健,支援 SSO、記住登入、多裝置管理。
  2. 舊專案快速修復:方案一(設定 session.cookie_lifetime)成本最低,立即生效。
  3. IE6-9 佔比極低(< 0.5%),若不需支援可直接忽略此問題。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved