PHP跨目录调用session时新建会话文件问题求助
问题背景
tillBrowserIsOpen.php、1days.php、2days.php三个文件在同一目录,10days.php在另一个目录。测试后发现10days.php会新建会话文件,无法复用之前的会话,怀疑是不同目录的Cookie路径导致服务器创建独立会话。
测试流程
- 运行tillBrowserIsOpen.php
- 关闭浏览器
- 运行1days.php
- 运行2days.php
- 运行show_cookie.php确认
$_COOKIE['PHPSESSID']存在 - 运行10days.php
- 运行show_session.php
- 运行show_cookie.php
预期结果
- 服务器创建后缀为...5b的会话文件,将...5b存入
$_COOKIE['PHPSESSID'] - 关闭浏览器后
$_COOKIE['PHPSESSID']被删除 - 创建后缀为...aa的新会话文件,将...aa存入
$_COOKIE['PHPSESSID'],有效期1天 - 运行2days.php时,
session_start()通过传递的$_COOKIE['PHPSESSID']连接...aa文件,并更新有效期为2天 - 确认客户端
$_COOKIE['PHPSESSID']值为...aa - 10days.php应复用现有会话,而非新建会话文件,否则
$_SESSION['10days']数据无法访问 $_SESSION应包含10days.php的数据$_COOKIE['PHPSESSID']值与2days.php的session_id()一致
实际现象
运行10days.php时新建了会话文件,show_session.php显示$_SESSION无10days.php的数据,show_cookie.php显示$_COOKIE['PHPSESSID']仍为2days.php的session_id()
相关代码
show_cookie.php
<?php echo "<pre>"; echo "cookie"; print_r($_COOKIE); echo "<br/>";
show_session.php
echo "<pre>"; echo "SESSION"; print_r($_SESSION); echo "<br/>";
tillBrowserIsOpen.php
<?php session_start(); $_SESSION['uponBrowserClosing'] = 'uponBrowserClosing'; setcookie(session_name(), session_id(), 0); echo "<pre>"; echo "cookie"; print_r($_COOKIE); echo "<br/>"; echo "server"; print_r($_SESSION); echo "</pre>"; echo session_id();
1day.php
<?php session_start(); $_SESSION['1days'] = '1days'; setcookie(session_name(), session_id(), time() + (24 * 3600)); echo "<pre>"; echo "cookie"; print_r($_COOKIE); echo "<br/>"; echo "server"; print_r($_SESSION); echo "</pre>"; echo session_id();
2days.php
<?php session_start(); $_SESSION['2days'] = '2days'; setcookie(session_name(), session_id(), time() + (2 * (24 * 3600))); echo "<pre>"; echo "cookie"; print_r($_COOKIE); echo "<br/>"; echo "server"; print_r($_SESSION); echo "</pre>"; echo session_id();
10days.php
<?php session_start(); $_SESSION['10days'] = '10days'; setcookie(session_name(), session_id(), time() + (10 * (24 * 3600))); echo "<pre>"; echo "cookie"; print_r($_COOKIE); echo "<br/>"; echo "server"; print_r($_SESSION); echo "</pre>"; echo session_id();
问题原因与解决方法
原因
PHP默认会把会话Cookie的路径设置为当前脚本所在的目录。也就是说,tillBrowserIsOpen.php、1days.php、2days.php所在目录的Cookie,浏览器只会在访问该目录下的脚本时发送;而10days.php在另一个目录,浏览器不会把之前的PHPSESSID Cookie发送过去,导致session_start()无法找到对应会话,只能新建一个。
解决方法
方法1:在setcookie时指定根路径
修改所有文件中的setcookie调用,添加路径参数'/',让Cookie在整个域名下生效:
// tillBrowserIsOpen.php中的setcookie修改为 setcookie(session_name(), session_id(), 0, '/'); // 1days.php中的setcookie修改为 setcookie(session_name(), session_id(), time() + (24 * 3600), '/'); // 2days.php和10days.php同理,都加上第四个参数'/'
方法2:全局配置PHP会话Cookie路径
修改php.ini中的session.cookie_path配置项,设置为根目录:
session.cookie_path = "/"
修改后重启PHP服务,所有会话Cookie都会默认使用根路径,跨目录脚本就能共享会话。
验证效果
修改后重新执行测试流程,10days.php会复用之前的PHPSESSID,不会新建会话文件;show_session.php能看到$_SESSION包含1days、2days和10days的数据;show_cookie.php显示的PHPSESSID与2days.php的session_id()一致。
内容的提问来源于stack exchange,提问作者soLo

