这是NOT,是this Q&A的复制品,因为我判断了那个问答的每一个答案,但他们都没有改善这里的情况.

同样的情况也适用于this Q&Athis 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.php session_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.ukwww.domain.ukdomain.uk,这些都不起作用.
  • 禁用Firefox的"增强跟踪保护"并不能解决这个问题.

需要强调的是,问题似乎不是会话机制本身,但不知何故,浏览器(Firefox 115)似乎并没有保存[对吗?]会话ID与Cookie或类似的不一致.

推荐答案

基于Cookie的会话的问题,只在Firefox中表现出来,很可能与Firefox不久前推出的Enhanced Tracking Protection(June 2019Firefox 67)有关.

如果只是在您的本地浏览器中关闭它,就已经将问题"修复"到对您必要的程度,那么我想,这可以被认为是这里的解决方案.如果您需要此功能也适用于其他用户-如果他们遇到问题,您可能必须指示他们也关闭此功能-或者调查是否有方法可以避免合法使用 case .(我不太了解它是如何工作的,无论它是基于一系列已知的"跟踪器",还是基于某种启发式方法--或者可能两者兼而有之.)

Php相关问答推荐

此行动未经授权.升级Laravel时

如何在Livewire中验证多个 Select 字段

输入手写CSV时在PHP中进行日期判断

启用额外的WooCommerce产品库存位置

从WooCommerce Checkout Country Select2下拉列表中重新排序国家/地区

如果再次调用SESSION_START(),会话.gc-max是否会重新启动?或者它是从第一次创建会话开始计算的?

PHP中冒号的奇怪用例

基于不用于变体的产品属性隐藏多个WooCommerce发货方式

PHP MySQL求和子树并与父树累加

将一个按钮添加到WooCommerce产品的管理视图中,该按钮链接到一个自定义的WebHook,并在末尾附加产品ID

如何从Laravel中的Spatie\Dns\Records\A对象中提取IP地址

SFTP在PHP(phpseclib3\Net\SFTP)-过滤目录列表结果服务器端可能吗?类似于psftp中的LS命令?

如果所有请求都通过index.php路由,如何使用htaccess文件强制使用HTTPS?

既然setSQLLogger()已被弃用,如何使用中间件在 Doctrine 3 中记录查询执行时间?

Symfony:从控制器内部调用自定义命令

WooCommerce 回购自定义插件:如何更新用户钱包?

如何限制 woocommerce 中相关产品的标题长度

simplexml_load_file 和 simplexml_load_string 返回具有不同编码的相同数据

Composer自动加载器重复了子类的类文件路径

Docker: unixodbc.h 没有这样的文件或目录.已安装 unixodbc-dev 时出现pecl install sqlsrv错误