為什麼當我瀏覽網站頁面時我的 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()
新增到每個頁面。我建議創建一個包含在所有頁面中的單個標頭文件,它對於設置所有頁面上所需的其他內容也很有用,例如如果用戶未登錄則重定向到登錄屏幕.