在 Linux 環境下,若 php.ini 中 session.use_trans_sid = 1 或編譯啟用 --enable-trans-sid,PHP 會在用戶禁用 Cookie 時自動在 URL 附加 PHPSESSID 參數傳遞 Session ID。這不僅影響 URL 美觀與 SEO,還可能導致 Session 固定攻擊風險。本文提供徹底解決方案。
session.use_trans_sid 啟用時,PHP 輸出缓冲區會自動重寫所有相對鏈接、表單 action、甚至 <a> 標簽,注入 PHPSESSID=xxx 參數。此行為由 output_add_rewrite_var() 實現,影響範圍不可控。
; 禁用透明 Session ID 傳遞 session.use_trans_sid = 0 ; 確保僅使用 Cookie 傳遞 Session ID session.use_cookies = 1 session.use_only_cookies = 1
<?php
// 必須在 session_start() 之前調用
ini_set('session.use_trans_sid', '0');
ini_set('session.use_only_cookies', '1');
session_start();
?>
<?php
// 移除 PHP 自動添加的重寫變量
output_reset_rewrite_vars();
// 或顯式移除特定變量(PHP 7.1+)
output_remove_rewrite_var('PHPSESSID');
?>
ThinkPHP / Laravel 等框架的 URL 生成方法通常已內置過濾,若手動拼接 URL 需注意:
// 手動構造 URL 時確保不攜帶 PHPSESSID $url = 'https://example.com/page?param=value'; // 正確 // 避免從 $_SERVER['REQUEST_URI'] 直接獲取(可能包含 PHPSESSID)
<a href>、<form action> 應無 PHPSESSIDphpinfo() 中 session.use_trans_sid 顯示 Off / 0| 現象 | 原因 | 解決 |
|---|---|---|
| 改了 php.ini 不生效 | 未重啟 PHP 進程、或運行時被框架覆蓋 | 重啟服務、檢查框架啟動文件是否調用 ini_set 開啟 |
| URL 仍有 PHPSESSID | 瀏覽器緩存、或代理/CDN 緩存舊頁面 | 強制刷新、清理 CDN 緩存、檢查響應頭 Cache-Control |
| 用戶禁用 Cookie 無法登錄 | 關閉 trans_sid 後無降級方案 | 引導用戶啟用 Cookie、或實現 Token 驗證機制(JWT/API Key) |
<?php
function removeUrlParam($url, $paramName) {
$parsed = parse_url($url);
parse_str($parsed['query'] ?? '', $query);
unset($query[$paramName]);
$newQuery = http_build_query($query);
return $parsed['scheme'] . '://' . $parsed['host'] .
($parsed['port'] ? ':' . $parsed['port'] : '') .
$parsed['path'] .
($newQuery ? '?' . $newQuery : '') .
($parsed['fragment'] ? '#' . $parsed['fragment'] : '');
}
// 使用示例
$url = 'https://example.com/page?PHPSESSID=abc123&foo=bar';
echo removeUrlParam($url, 'PHPSESSID');
// 輸出: https://example.com/page?foo=bar
?>