Данные сеанса PHP не сохраняются

ДЛЯ ВЕРСИИ TL; DR ... ПЕРЕЙДИТЕ ВНИЗ И ПРОЧИТАЙТЕ, ЧТО ВЫДЕЛено жирным шрифтом

Хорошо, у меня была эта проблема какое-то время, я провел много исследований, внес некоторые изменения и до сих пор понятия не имею, что не так с моим кодом. Моя проблема в том, что когда пользователь отправляет регистрационную форму, сеанс всегда возвращается к пустому. Вот как выглядит логика:

1. Пользователь переходит к mysite / register / и получает доступ к register.php через index.php в том же каталоге. 2. index.php обрабатывает все (вызывает классы для логики и тому подобное, но все выполняется через index.php на верхнем уровне)
3. Пользователь отправляет форму входа через ajax-вызов vanilla.js, и в ответ console.infos возвращается.

Теперь, когда вы понимаете логику ... позвольте мне перейти к коду:

Вот index.php:

<?php
// Allowing PHP to be strictly typed and start session
declare(strict_types=1);
session_start();

// Requiring the necessary classes
require_once "../vendor/autoload.php";
require_once "../model/EditSession.php";
require_once "../model/DatabaseConfig.php";
require_once "../model/ServerValidation.php";
require_once "../model/RegisterUser.php";
require_once "../model/Verify.php";

// Creating the new objects
$validatingServer = new ServerValidation();
$sessionToEdit = new EditSession();
$sessionToEdit->create_new_session_id();

// Checks the request protocol
try {
    $validatingServer->checkHttps();
} catch (Exception $ex) {
    header("Location: /NotSecure.php");
}

// Setting CSRF token for protection
try {
    $csrfToken = $sessionToEdit->store_secure_key_in_session("CSRFTOKEN");
} catch (Exception $ex) {
    echo "You have a problem setting your session. $ex";
}

// Handling a navigation to the webpage
$validatingServer->navigateToWebsite("register.php", "Register", $csrfToken);
        // For when a user submits the form
        try {
            $validatingServer->checkRequestType("POST");
            $validatingServer->checkContentType("application/json");
            $registerFormData = json_decode(file_get_contents("php://input"), true);
            $csrfTokenFromForm = $registerFormData["csrfToken"];
            $csrfTokenFromSession = $sessionToEdit->get_from_session("CSRFTOKEN");
        } catch (Exception $ex) {
            echo "Bad request data. $ex";
        }
        //$validatingServer->checkToken($csrfTokenFromForm, $csrfTokenFromSession);

        // Call to make original register user object
        try {
            $register = new RegisterUser($registerFormData["firstName"], $registerFormData["lastName"], $registerFormData["email"], $registerFormData["password"]);
        } catch (Exception $ex) {
            echo $ex;
        }

        // Check email and register the user
        try {
            $register->checkEmail();
            $register->register();
        } catch (Exception $ex) {
            echo $ex;
        }

        // Sending registration email to the user
        try {
            $register->sendRegistrationEmail("http://localhost/");
        } catch (Exception $ex) {
            echo $ex;
        }

        echo "Successful Register";

Вот фронтенд

<!doctype html>
<html>

<head>

<title><?=$pageTitle;?></title>

</head>

<body>

<main>

<form id = "registerForm">
<input type = "text" id = "firstName" name = "firstName" autocomplete = "given-name" placeholder = "First Name" pattern = "^[A-Za-z.\s_-]+$" autofocus required>
<input type = "text" id = "lastName" name = "lastName" autocomplete = "family-name" placeholder = "Last Name" pattern = "^[A-Za-z.\s_-]+$" required>
<input type = "email" id = "email" name = "email" autocomplete = "email" placeholder = "Email" required>
<input type = "password" id = "password" name = "password" placeholder = "Password" pattern = "^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\$%\^&\*]).{8,}" required>
<input type = "hidden" id = "csrfToken" value = "<?=$csrfToken;?>">
<button type = "submit" id = "registerSubmit">Submit</button>
</form>

</main>
<script src = "index.js"></script>
</body>
</html>

Вот index.js

const registerForm = document.getElementById("registerForm");
registerForm.addEventListener("submit", function(e) {
    e.preventDefault();
    const firstName = document.getElementById("firstName").value;
    const lastName = document.getElementById("lastName").value;
    const email = document.getElementById("email").value;
    const password = document.getElementById("password").value;
    const csrfToken = document.getElementById("csrfToken").value;
    const registerFormData = {
        "firstName":firstName,
        "lastName":lastName,
        "email":email,
        "password":password,
        "csrfToken":csrfToken
    };
    const ajax = new XMLHttpRequest();
    ajax.open("POST", "index.php");
    ajax.setRequestHeader("Content-Type", "application/json");
    ajax.withCredentials = true;
    ajax.send(JSON.stringify(registerFormData));
    ajax.onload = function() {
        console.info(this.response);
    }
}, false);

Вот EditSession.php

<?php 
declare(strict_types=1);
class EditSession {

    private $firstPartOfNewId;
    private $secondPartOfNewId;
    private $thirdPartOfNewId;
    private $newSID;
    public $secureKey = "";

    // Create new session ID
    function create_new_session_id() : void {

        if (isset($_SESSION)) {
            $firstPartOfNewId = str_replace(array(".", ":"), "", $_SERVER["REMOTE_ADDR"]);
            $secondPartOfNewId = round(microtime(true) * 1000);
            $thirdPartOfNewId = hash("sha512", random_bytes(64));
            $newSID = $firstPartOfNewId.$secondPartOfNewId.$thirdPartOfNewId;
            session_id($newSID);
        } else {
            throw new Exception("Session is not set");
        }

    }

    // Store a value in a set session
    function store_in_session(string $key,string $value) : void {

        if (!isset($_SESSION)) {
            throw new Exception("Session is not set.");
        }

        if (!isset($_SESSION[$key])) {
            $_SESSION[$key] = $value;
        }

    }

    // Store a value in a set session
    function store_secure_key_in_session(string $key) : string {

        if (!isset($_SESSION)) {
            throw new Exception("Session is not set.");
        }

        if (!isset($_SESSION[$key])) {
            $secureKey = hash("sha512", random_bytes(64));
            $_SESSION[$key] = $secureKey;
            return $secureKey;
        } else {
            return $secureKey;
        }

    }

    // Unsetting variable associated with the $key
    function unset_session_variable(string $key) : void {

        if (isset($_SESSION)) {
            $_SESSION[$key] = "";
            unset($_SESSION[$key]);
        } else {
            throw new Exception("Session with key is not set.");
        }

    }

    // Getting associated key from session
    function get_from_session(string $key) : string {

        if (isset($_SESSION[$key])) {
            return $_SESSION[$key];
        } elseif (isset($_SESSION)) {
            throw new Exception("Session is set, but the key passed is not set in the session.");
        } else {
            throw new Exception("Session is not set.");
        }

    }

}

?>

Вот ServerValidation.php

<?php
declare(strict_types=1);
class ServerValidation {

    // Handles navigation to website
    function navigateToWebsite(string $page, string $pageTitle, string $csrfToken) : void {
        if (empty($_POST) && empty($_GET) && empty(file_get_contents("php://input"))) {
            $csrfToken = $csrfToken;
            $pageTitle = $pageTitle;
            include_once $page;
            exit;
        }
    }

    // Checks if the website is served over https or its localhost
    function checkHttps() : void {
        if ($_SERVER["REQUEST_SCHEME"] !== "https" && $_SERVER["HTTP_HOST"] !== "localhost") {
            throw new Exception("Not served over https");
        }
    }

    // Checks if the content type is what it should be
    function checkContentType(string $type) : void {
        if ($_SERVER["CONTENT_TYPE"] !== $type) {
            throw new Exception("Wrong content-type");
        }
    }

    // Checks request method
    function checkRequestType(string $type) : void {
        if ($_SERVER["REQUEST_METHOD"] !== $type) {
            throw new Exception("Wrong request method");
        }
    }

    function checkToken(string $tokenFromFrontend, string $tokenFromSession) : void {
        if ($tokenFromSession !== $tokenFromFrontend) {
            throw new Exception("Tokens not matching up, there is a problem!!");
        }
    }

}

Теперь вот что происходит с кодом. Когда пользователь отправляет регистрационную форму с помощью csrfToken, который извлекается из скрытого значения в форме с помощью AJAX, я получаю исключение в моей программе (в частности, из метода checkToken() в классе ServerValidation), в котором говорится, что «токены не совпадают. ". И я подтвердил, почему это так. Если я var_dump $ _SESSION сразу после вызова session_start (), ВСЕГДА будет пустым. Не имеет значения, был ли он уже инициализирован (пользователем, впервые переходящим на страницу), он ВСЕГДА пуст. Итак, следуя логике программы, она вставляет новое значение для CSRFTOKEN, и поэтому, конечно, они не совпадают. Я в полном тупике и неделю работаю над этой проблемой. Вот несколько ответов на вопросы, которые, я знаю, вам зададут:

1. Я использую macbook с XAMPP и php 7.2

. 2. Мои файлы cookie установлены на http_only, но не на secure_only. Все остальные параметры файлов cookie заданы по умолчанию. 3. Мои права доступа к файлам, в которых хранятся данные моего сеанса (/ Applications / XAMPP / xamppfiles / temp /), равны 777 (я просто хотел сделать что-то, что, я знаю, будет работать)

4. Что произойдет, если я не создам новый php session_id? Произойдет тот же результат ... т.е. сеанс будет по-прежнему всегда инициализирован как empty

5. Могу ли я var_dump сеанса в разных точках программы? Конечно ... вот разные моменты и их результаты:

- Сразу после вызова session_start:
- Когда пользователь изначально переходит на страницу: пустой сеанс. - Когда пользователь отправил регистрационную форму: пустая сессия

- Сразу после того, как $csrfToken = $sessionToEdit->store_secure_key_in_session("CSRFTOKEN"); называется:
- Когда пользователь изначально переходит на страницу: возвращается сеанс с ключом CSRFTOKEN
- Когда пользователь отправил регистрационную форму: возвращается сеанс с ключом CSRFTOKEN (но значение отличается от того, когда пользователь изначально перешел на страницу)

- Сразу после $validatingServer->navigateToWebsite("register.php", "Register", $csrfToken);
- Когда пользователь сначала переходит на страницу: ничего, потому что программа не заходит так далеко, потому что выходит из нее. - Когда пользователь отправил регистрационную форму: возвращается сеанс с ключом CSRFTOKEN (но значение отличается от того, когда пользователь изначально перешел на страницу, и значение отличается от того, что находится в скрытом поле в регистрационной форме. )


Вот вопрос: Почему значения моего сеанса продолжают инициализироваться пустыми, даже если я нахожусь в том же домене, выполняю всю свою работу в одном файле, правильно ли заданы параметры сеанса и права доступа к файлу установлены правильно?

Вы проверили, правильно ли клиент отправляет идентификатор сеанса?

CBroe 17.07.2018 09:28

@CBroe, о каком методе ты говоришь?

Adam McGurk 17.07.2018 14:07

Какой вам нравится ...? Теперь уверен, в чем вопрос.

CBroe 17.07.2018 14:15

@CBroe ну, что вы имеете в виду, убедитесь, что клиент отправляет правильный идентификатор сеанса?

Adam McGurk 17.07.2018 14:17

Да, конечно (а также, что он также правильно принимается внутри серверного скрипта) ... поскольку это основа для правильной работы сеансов, это также должно быть первое, что вы проверяете.

CBroe 17.07.2018 14:27

@CBroe, я проверил это, и ответ отрицательный. Вот почему сеанс каждый раз инициализируется как пустой.

Adam McGurk 17.07.2018 14:28
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
6
68
0

Другие вопросы по теме