PHP会话数据不持久

时间:2018-07-17 05:46:54

标签: php session session-variables session-cookies

对于TL; DR版本...转到底部并阅读加粗的内容

好的,所以我有一段时间了这个问题,并且我做了很多研究,做了一些更改,但仍然不知道我的代码有什么问题。我的问题是,当用户提交注册表格时,会话总是恢复为空。逻辑如下:

1.用户导航到mysite / register /,并通过同一目录中的index.php提供register.php的服务。
2. index.php处理所有内容(调用具有这种性质的逻辑和内容的类,但所有内容都在顶层通过index.php运行)
3.用户通过vanilla.js ajax调用提交登录表单,并返回console.logged响应。

现在您已经了解了逻辑……让我开始介绍代码:

这是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.log(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!!");
        }
    }

}

现在,这是代码发生的情况。当用户提交注册表单,并使用AJAX从表单中的隐藏值中获取csrfToken时,我在程序中抛出了异常(特别是从ServerValidation类的checkToken()方法中抛出),该异常显示为“令牌不匹配”。我已经证实了这是为什么。如果我在调用session_start()之后立即var_dump $ _SESSION,则始终为空。它是否已经初始化(由用户首先导航到页面)无关紧要,它始终为空。因此,按照程序的逻辑,它将为CSRFTOKEN插入一个新值,因此它们当然不匹配。我绝对很沮丧,并且一直在解决这个问题一个星期。以下是一些我会问到的问题的答案:

1.我正在使用运行XAMPP和php 7.2的macbook

2.我的cookie设置为http_only,但不是secure_only。其他所有cookie参数均为默认设置。

3.我的会话数据(/ Applications / XAMPP / xamppfiles / temp /)的存储文件权限为777(我只想做我知道会做的事情)

4.如果不创建新的php session_id,会发生什么?将会发生相同的结果...即,会话仍将始终初始化为空

5.我可以在程序的不同点上var_dump会话吗?当然...这里有不同的地方及其结果:

-在session_start之后立即被调用:
    -用户最初导航至页面时:一个空会话。
    -用户提交注册表格后:空会话

-在$csrfToken = $sessionToEdit->store_secure_key_in_session("CSRFTOKEN");被调用之后:
    -当用户最初导航至页面时:返回带有CSRFTOKEN键的会话
    -用户提交注册表后:将返回带有CSRFTOKEN密钥的会话(但该值与用户最初导航至页面时的值不同)

-就在$validatingServer->navigateToWebsite("register.php", "Register", $csrfToken);之后
    -用户最初导航至页面时:什么都没有,因为该程序由于退出而不能走得太远。
    -用户提交注册表后:返回带有CSRFTOKEN密钥的会话(但该值不同于用户最初导航至页面时的值,并且该值不同于注册表中隐藏字段中的值) )


这是一个问题:为什么我的会话值总是初始化为空,即使我在同一个域中,我的所有工作都在同一个文件中,我的会话参数设置正确,并且我的文件权限设置了对吧?

0 个答案:

没有答案