为什么当我浏览网站页面时我的 php 会话没有保存?
我正在创建一个网站,该网站使用简单的用户名-密码对来允许管理员在登录页面上验证自己的身份。为此,首先当用户到达主页时创建一个会话,然后当他们单击登录按钮时,他们将被重定向到一个表单以输入用户名和密码,然后该表单通过 POST 方法发送到另一个验证用户名和密码是否有效的页面,在会话中放入一个包含登录管理员用户名的变量,然后重定向到管理员仪表板,验证该变量是否设置为检查是否确实是管理员在页面上。
正如标题中所解释的,主要问题是当我测试主页时确实创建了一个会话,但是当我单击登录表单的链接时,会话似乎被破坏了,尽管我删除或中和任何可能导致这样做的指令。
主页上启动会话的小 php 片段 (main.php)
<?php session_start(['cookie_lifetime' => 86400]); $_SESSION["start"] = time(); error_log("Test de session : ".session_status()." | ".$_SESSION["start"]."; \n", 3, "log1.txt"); //puts in the log the session status and the content of the variable assigned above. if (!is_writable(session_save_path())) { error_log('Session path '.session_save_path()." is not writable for PHP; \n", 3, "log1.txt"); } else { error_log('Session path '.session_save_path()." is writable for PHP; \n", 3, "log1.txt"); } ?>
我尝试覆盖 cookie 生命周期,如上所示,获取了该问题答案的片段,以查看该文件夹是否可写以及会话是否已创建。 日志始终返回主页:
Test de session : 2 | 1684946314; Session path C:\MAMP\bin\php\sessions\ is writable for PHP;
(第一行|后面的数字是预期的时间戳)。
登录表单中唯一的 php 代码段 (connexion.php)
<?php if (isset($_SESSION["logged_admin"])) { header("Location: auth.php"); exit(); } error_log("Test de session : ".session_status()." | ".$_SESSION["start"]."; \n", 3, "log1.txt"); if (!is_writable(session_save_path())) { error_log('Session path '.session_save_path()." is not writable for PHP; \n", 3, "log1.txt"); } else { error_log('Session path '.session_save_path()." is writable for PHP; \n", 3, "log1.txt"); } ?>
我已经将第一个 if 放在那里,以便将登录的管理员直接重定向到仪表板(如果他们已经连接)。之后的行执行与 main.php 中相同的测试,但这次在日志中返回:
Test de session : 1 | ; Session path C:\MAMP\bin\php\sessions\ is writable for PHP;
这表明会话已被销毁并且其所有变量均未设置。
php 文件中负责检查提供的与会话使用相关的用户名和密码的部分代码(auth.php)
<?php error_log("\n\n------- [AUTH START ".date(DATE_RFC2822)." ] -------\n", 3, "log1.txt"); $fail = 0; /*if (isset($_SESSION["logged_admin"]) && isset($_SESSION['start']) && (time() - $_SESSION['start'] > 1800)) { session_unset(); session_destroy(); session_start(['cookie_lifetime' => 86400]); $_SESSION["start"] = time(); error_log("Session expirée (connecté + de 30 min);\n", 3, "log1.txt"); echo "Votre session a expirée. Veuillez vous reconnecter."; $fail = 1; goto fail; }*/ //code that checks if a session is loaded during too much time and if yes, destroys it. I've put the code in a comment so it normally shouldn't be executed by the server. error_log("Test de session : ".session_status()." | ".$_SESSION["start"]."; \n", 3, "log1.txt"); if (!is_writable(session_save_path())) { error_log('Session path '.session_save_path()." is not writable for PHP; \n", 3, "log1.txt"); } else { error_log('Session path '.session_save_path()." is writable for PHP; \n", 3, "log1.txt"); } //Here's once again the similar tests done in the other files. if (isset($_SESSION["logged_admin"])) { error_log("L'administrateur est déjà connecté;\n", 3, "log1.txt"); goto fail; } //Other stuff that verifies if the data sent with POST method is there and connecting the local server to the database i use. $Accounts = $AccountsQuery->fetchAll(); //Converts the data i've received via a SQL query foreach ($Accounts as $Compte) { if ($Compte["login"] == $login && $Compte["mdp"] == $mdp) { $_SESSION["logged_admin"] = $login; //if a username-password couple from the registered admins corresponds to the couple sent via the log in form, the username retrieved from the log in form ($login) is associated to the session's array. error_log(session_status()."; \n", 3, "log1.txt"); error_log("Login et mot de passe valides | ".var_dump($_SESSION["logged_admin"])." est désormais connecté sur la session ".session_id()." ;\n", 3, "log1.txt"); goto fail; } } $fail = 1; error_log("Login et mot de passe invalide; \n", 3, "log1.txt"); echo "L'identifiant ou le mot de passe fourni est invalide."; ?>
提交表单后执行文件返回的日志:
------- [AUTH START Wed, 24 May 2023 16:49:17 +0000 ] ------- Test de session : 1 | ; Session path C:\MAMP\bin\php\sessions\ is writable for PHP; PDO set up for authentification; 1; Login et mot de passe valides | est désormais connecté sur la session ; Authentification réussie le Wed, 24 May 2023 16:49:17 +0000 - British GMT hour ----------------------- [AUTH END]
由于我已将注册的管理员凭据放入表单中,身份验证本身成功,但在单击访问登录表单后,在主页中创建的会话被证明仍然被删除,因此无法将用户名放入$_SESSION 数组中已登录的管理员。
if 结构可防止未经授权的用户访问仅限管理的仪表板内容 (dashboard.php)
<?php if (isset($_SESSION["logged_admin"])) { ?> //If there's a logged-in admin, shows up the dashboard with the admin-stuff to do. <?php } else { echo "Vous ne pouvez pas accéder à cette page car vous n'êtes pas connecté. Veuillez vous rediriger vers la page principale."; }; ?> //Else shows the user on the page that he isn't logged-in.
我的服务器(php 8.1.0)中使用的PHP组件的两个配置文件摘录
php.ini-development
... ; ; where MODE is the octal representation of the mode. Note that this ; does not overwrite the process's umask. ; https://php.net/session.save-path session.save_path = "tmp/"
php.ini-生产
; ; where MODE is the octal representation of the mode. Note that this ; does not overwrite the process's umask. ; https://php.net/session.save-path session.save_path = "tmp/"
session.save_path 参数在两者中显然都没有注释。但是,它不是 session_save_path() 函数返回的路径。
https://www.php.net/manual/en /function.session-start.php
每次加载新页面时,都是不同的 HTTP 请求。会话必须在每个 HTTP 请求上启动,因此,您必须将
session_start()
添加到每个页面。我建议创建一个包含在所有页面中的单个标头文件,它对于设置所有页面上所需的其他内容也很有用,例如如果用户未登录则重定向到登录屏幕.