这是NOT,是this Q&A的复制品,因为我判断了那个问答的每一个答案,但他们都没有改善这里的情况.
是的,这个问题是一个"classic "问题,但我不知道如何诊断这个问题:会话被保存到文件中,会话文件保存所有相关数据,但在每次页面加载时,PHP系统都没有找到现有的会话文件,而是生成了一个新的会话.
我无论如何也不明白为什么会发生这种事.
最新情况:
今天早上(8月1日),我发现Firefox最近更新到115似乎有一个副作用,即Firefox浏览器无法保存/加载/使用/访问包含会话ID的Cookie,否则会话ID不会保存到Cookie中.请参阅此问题底部的"更新"详细信息.
Opera、Chrome和Edge浏览器运行良好,可以正常传输会话.
Server
- 服务器运行在Plesk Obsidian 18.0.54上,目前运行的是PHP 7.4.33
- 服务器currently将PHP作为"由apache 服务的FPM应用程序"来运行(见最下面的注释).
- 服务器之前在"原始"状态下运行一切都完全正常,没有任何问题.
- 使用文件系统保存会话.
- 磁盘空间使用没有问题.
有些东西已经改变了,现在不能在页面之间传输PHP会话ID.每个页面都会启动一个新会话.
Local PHP.ini
本地PHP ini文件具有以下设置:
Session.save_path="/path/to/domain.uk/sessionFolder"
Ession.name="随机字符串89"
Ession.use_only_cookies=1
Session.cookie_httponly=1
Session.cookie_secure=1
Ession.cookie_samesite="Strong"
会话.cookie_DOMAIN=".domain.uk"
会话.cookie_Path=/
Ession.sid_long=128
我已经调整了其中的一些设置(探索cookie_samesite="Lax"
),并删除了字符串两边的引号,但这些对问题没有任何影响.
Original Structure
有问题的第一页(A.php
)有几个包含的文件:
A.php
-- Header.php
-- Preloader.php
-- Core page script
100
一个标准的标题,对网站上的所有页面都是通用的,它设置标题信息,如HTTP标题,并确保自动加载器设置正确,并且PHP会话处于活动状态.
error_reporting(E_ALL &~E_NOTICE);
if (session_status() === PHP_SESSION_NONE){
session_set_cookie_params( 4000, '/', '.domain.uk' , true, true );
session_start();
}
header("Cache-Control: no-cache, must-revalidate"); //HTTP 1.1
header('Content-Type: text/html; charset=utf-8');
header("Content-Language: en");
header("Content-Security-Policy: upgrade-insecure-requests;");
header("Referrer-Policy: origin-when-cross-origin"); //referrer for Chrome
header("Referrer-Policy: strict-origin-when-cross-origin");
...
use \namespace\reference\donehere;
// custom autoloader (100% works)
require str_ireplace("/public_html","/classes",$_SERVER['DOCUMENT_ROOT'])."/autoloader.php";
我已经研究了各种变化,比如将会话cookie生存期设置为0
,确认域是正常的,甚至完全禁用session_set_cookie_params()
行.这种行为没有任何变化.
preloader.php
After the header, the first page loads a "preload" include script which sets a few session variables for use for the entire client visit. This works perfectly and only interacts with sessions here:
if( empty($_SESSION['reference']) || (time() - (int)$_SESSION['referenceTime']) > 15 ) {
$_SESSION['reference'] = "generated value here";
$_SESSION['referenceTime'] = time();
error_log("\nNEW checkDrop set in ".__FILE__." as: ".print_r($_SESSION,true));
}
elseif(strlen($_SESSION['reference'])> 0) {
error_log("\ncheckDrop already exists: ".print_r($_SESSION,true));
}
这些都集中在第一页,A.php
页内:
100
<?php
use \namespace\reference\donehere;
require $_SERVER['DOCUMENT_ROOT']."/path/to/Header.php";
include $_SERVER['DOCUMENT_ROOT']."/path/to/preloader.php";
if (isset($_GET['msg'])) {
$_SESSION['message'] = trim(($_SESSION['message']??'').' '.urldecode($_GET['msg']));
}
?>
<!DOCTYPE html>
<html class="no-js" lang="en-GB">
<head>
<meta charset="utf-8">
<title>title</title>
<link rel="canonical" href="https://www.domain.uk/A.php" >
<?php
include $_SERVER['DOCUMENT_ROOT']."/path/to/html_only_metaHeader.php";
?>
</head>
<body>
<main>
<section>
<form name="form1" method="post" action="/B.php"
enctype="multipart/form-data" accept-charset="UTF-8">
然后是一个表单,其中包含一个包含一些会话数据的隐藏字段:
<input type='hidden' name='xxxx' value='<?php
// value comes from the preloader include above.
print $_SESSION['reference']??'';
?>'>
页面底部是会话调试输出,它始终显示正确的数据,与上面的HTML表单相同:
</body>
</html>
<?php
error_log("base of start: ".print_r($_SESSION,true));
error_log("Session ID: ". print_r(session_id()??'none',true));
B.php
- Header.php
- 在脚本中进行会话和后期数据处理.
仅此而已,原始页面不在同一文件夹中,但即使在同一文件夹中,会话也完全无法意识到存在与此相关联的现有会话
<?php
use \namespace\reference\donehere;
require $_SERVER['DOCUMENT_ROOT']."/path/to/Header.php";
error_log("Session ID 3: ". print_r(session_id()??'none',true));
error_log("name of session 3: ".print_r(session_name(),true));
我为探索这个问题所做的事情:
- 在所有页面/INCLUDE中,会话名称("随机字符串89")是通用的.
- (多产)错误日志(log)报告显示正在将会话数据写入文件.
- 我已经try 禁用/跳过
session_set_cookie_params
(无论如何都是在ini中设置的) - 正在try 将samesite.cookie设置为
Lax
- 并确保域对WWW开放
/
或开放.或其他变型.domain.uk
- Session status is confirmed as
"active" (2)
on all pages after the Header.phpsession_start();
- 没有空格(我可以看到)会干扰会话触发.
-
PHPinfo
没有显示任何意外情况,并且在"本地"列下显示一切正常. - 所有找到的StackOverGnome解决方案都无法解决此问题或不适用(在此问题的顶部列出)
- 我今天花了很多时间,有条不紊地研究了这里的可能性,但没有找到任何东西.我错过了什么?
如何诊断此问题?
- 服务器说明:服务器currently将PHP作为"由apache 提供服务的FPM应用程序"运行.这里有一些选项可以将其更改为"由nginx提供服务的fpm应用程序"或"fast CGI",我从未在此服务器上更改过此设置,也不确定这会导致什么后果?
Updates
我发现了一些意想不到的更新:这个问题似乎是Firefox 115特有的.我试过了Opera Browser(V100)、Chrome(V115)甚至MS Edge(V109),它们都运行得很好,但Firefox坚持不识别会话ID.奇怪的是,在其他网站(包括我的网站和第三方网站),Firefox没有出现登录问题,为什么这似乎是浏览器特有的问题.
要回答 comments 中的问题,请执行以下操作:
- 页面可以很好地保存会话数据,判断文件系统中的原始会话文件可以确认这一点.
- Every page loads "Header.php".
- 我试过使用
.domain.uk
和www.domain.uk
和domain.uk
,这些都不起作用. - 禁用Firefox的"增强跟踪保护"并不能解决这个问题.
需要强调的是,问题似乎不是会话机制本身,但不知何故,浏览器(Firefox 115)似乎并没有保存[对吗?]会话ID与Cookie或类似的不一致.