Я потратил пару месяцев на разработку приложения на моем домене. Это общая концепция. Во время разработки я принимал его сам в своем собственном домене, но недавно подтолкнул его к нашему фактическому. Проблема в том, что сеансы не создаются и не сохраняются между страницами, и я не могу для жизни понять, почему.
Извините за стену кода ниже, но я предпочитаю это теоретическое объяснение.
Давайте начнем с того, как начать сеанс в верхней части каждой страницы:
function sec_session_start() { $session_name = 'login'; $secure = false; $httponly = true; ini_set('session.use_only_cookies', 1); session_set_cookie_params(86400, '/', '.domain.com', $secure, $httponly); session_name($session_name); session_start(); session_regenerate_id(); }
И затем, как я проверяю, вошел ли пользователь в систему. Я добавил return x;
вместо false
для отладки. Я добавляю это к URL-адресу переадресации.
function login_check($mysqli) { if(isset($_SESSION['id'], $_SESSION['login_string'], $_SESSION['type'])) { $id = $_SESSION['id']; $login_string = $_SESSION['login_string']; $user_browser = $_SERVER['HTTP_USER_AGENT']; if($_SESSION['type'] == 1 || $_SESSION['type'] == 2) // Admin user { if ($stmt = $mysqli->prepare("SELECT `password` FROM `users` WHERE `id` = ? LIMIT 1")) { $stmt->bind_param('s', $id); $stmt->execute(); $stmt->store_result(); if($stmt->num_rows == 1) { $stmt->bind_result($password); $stmt->fetch(); $login_check = hash('sha512', $password.$user_browser); if($login_check == $login_string) { return true; } else { return 1; } } else { return 2; } } else { return 3; } } else if($_SESSION['type'] == 3) { // Standard user if($stmt=$mysqli->prepare("SELECT `password` FROM `proj` WHERE `id` = ? LIMIT 1")) { $stmt->bind_param("s", $_SESSION['id']); $stmt->execute(); $stmt->store_result(); if($stmt->num_rows == 1) { $stmt->bind_result($db_key); $stmt->fetch(); $login_check = hash('sha512', $db_key.$user_browser); if($login_check == $login_string) { return true; } else { return 4; } } } } else { return 5; } } else { return 6; } }
У меня есть две страницы входа, одна для администраторов и одна для пользователей.
Администратор:
<?php ini_set('display_errors','On'); error_reporting(E_ALL); include_once "../functions.php"; include_once "../db_connect.php"; sec_session_start(); if(login_check($mysqli) === true) { header('Location: ../index.php'); } else { // Login form }
Пользователи:
<?php ini_set('display_errors','On'); error_reporting(E_ALL); include_once "../functions.php"; include_once "../db_connect.php"; sec_session_start(); if(login_check($mysqli) === true) { header('Location: ../index.php'); } else { // Login form }
Совсем идентично, кроме источников файлов, поскольку admin login.php
находится в /admin
. Несмотря на это, первая отображает форму входа правильно, а вторая перенаправляет вас на index.php
(даже когда в инкогнито, тайна для меня), вызывая цикл переадресации (поскольку index.php
отправляет его обратно для входа в него) ,
В дополнение к этому, когда я login.php
систему с надлежащими учетными данными, он перенаправляет меня на index.php
только для перенаправления меня обратно в login.php
с кодом ошибки 6
.
Пожалуйста, сделайте комментарий, если вам нужна дополнительная информация или примеры кода, я чувствую себя потерянным в своем собственном проекте прямо сейчас.
Любая помощь приветствуется, спасибо
ОБНОВЛЕНИЕ 17 декабря:
После нескольких часов отладки мы пришли к выводу, что проблема связана не с кодом, а с конфигурацией сервера. Простой пример:
<?php session_start(); echo session_id(); ?>
Если вы откроете этот файл на рабочем сервере и обновите страницу, он отобразит новый идентификатор сеанса с каждым запросом. Почему-то я не знаю. Я подтвердил, что создан файл сеанса, а также файл cookie. Он содержит правильную информацию и может быть доступен SSH с разрешениями сервера. Поистине странное поведение.
Любые подсказки?
Я прошел через ваш код, и я не нашел ничего, кроме всего лишь 1 вещи.
Вы не должны использовать ==
для сравнения строк ===
в порядке.
$something = 0; echo ('password123' == $something) ? 'true' : 'false';
Запустите вышеуказанный код, и вы обнаружите причину потери сеанса. В вашей функции login_check вы используете ==
для сравнения двух строк
if($login_check == $login_string)
замените его:
if($login_check === $login_string)
Иначе все абсолютно безупречно. Если изменение этой мелочи не решит вашу проблему, просто дайте мне знать.
Вы подключаетесь к БД до начала сеанса. Я бы рекомендовал вам импортировать вашу функцию, а затем начать сеанс, а затем подключиться к базе данных.
include_once "../functions.php"; sec_session_start(); include_once "../db_connect.php";
Убедитесь, что сеанс уже запущен и убедитесь, что он выполняется только один раз:
С PHP> = 5.4:
function sec_session_start() { if (session_status() == PHP_SESSION_NONE) { $session_name = 'login'; $secure = false; $httponly = true; ini_set('session.use_only_cookies', 1); session_set_cookie_params(86400, '/', '.domain.com', $secure, $httponly); session_name($session_name); session_start(); session_regenerate_id(); } }
До PHP 5.4:
function sec_session_start() { if (session_id() == '') { $session_name = 'login'; $secure = false; $httponly = true; ini_set('session.use_only_cookies', 1); session_set_cookie_params(86400, '/', '.domain.com', $secure, $httponly); session_name($session_name); session_start(); session_regenerate_id(); } }
Кроме того, почему сеанс нужно восстанавливать каждый раз?
Я испытал подобную проблему несколько месяцев назад на моем рабочем сервере, где заканчивались сессии (например, в ваших случаях сеансы теряются между страницами), и пользователи внезапно вышли из моего сайта. Поэтому после нескольких дней отладки все было сведено к этим трем строкам в файле php.ini .
Из руководства ,
session.gc_probability в сочетании с session.gc_divisor используется для управления вероятностью запуска программы gc (сборка мусора). По умолчанию 1.
session.gc_divisor в сочетании с session.gc_probability определяет вероятность запуска процесса gc (сборка мусора) при каждой инициализации сеанса. Вероятность вычисляется с использованием gc_probability / gc_divisor, например, 1/100 означает, что вероятность каждого процесса GC начинается с 1%. session.gc_divisor по умолчанию – 100.
session.gc_maxlifetime указывает количество секунд, после которых данные будут считаться «мусором» и потенциально очищены. Сбор мусора может произойти во время сеанса (в зависимости от session.gc_probability и session.gc_divisor).
И это были мои первоначальные конфигурации сеансов в файле php.ini, которые на самом деле создали всю неприятность в первую очередь,
session.gc_divisor 1000 1000 session.gc_maxlifetime 1440 1440 session.gc_probability 0 0
Таким образом, это означает, что сборщик мусора начнет с вероятности session.gc_probability, деленной на session.gc_divisor. И используя значения по умолчанию для этих параметров (соответственно 0 и 1000), вероятность сбора мусора = session.gc_probability / session.gc_divisor, то есть 0/1000 = 0%, что, по моему мнению, неверно, плюс session.gc_maxlifetime показалось мне слишком низким ,
Итак, я решил изменить настройки сеанса в файле php.ini и включил эти значения,
session.gc_probability = 1 session.gc_divisor = 1000 session.gc_maxlifetime = 28800
И с тех пор все работает нормально. Поэтому мое предложение для вас, проверьте эти три значения в файле php.ini и при необходимости измените их в соответствии с вашими потребностями.
У меня был аналогичный опыт в прошлом, я точно не помню, как я решаю эту проблему, но из того, что я помню, это связано с кукисами сеансов и переменным порядком в PHP.
найдите эту строку ниже в php.ini,
variables_order = "GPCS"
так или иначе, изменение порядка этих варов повлияло на сеанс PHP.
если по каким-либо изменениям, как и я, вы не можете изменить настройки на сервере, вы также можете попробовать дублировать cookie сессии с помощью обычного файла cookie, выполнив следующие действия:
session_start(); set_cookie(session_name(), session_id());
и другое примечание, у другого браузера также есть другое поведение в cookie сеанса, например: сафари. на сафари, я должен дублировать файл cookie, независимо от переменной последовательности.
Надеюсь, поможет
Я также столкнулся с этой проблемой, но это была установка ssl, которая изменила ссылку на базовый файл с https, а файл отправки был без ссылки ssl. Также мне пришла в голову продолжительность сеанса. Помимо этого, мой провайдер хостинга может объяснить это.