Mysql Как правильно проверять срок годности cookie на стороне сервера?

ImperatorR

Новичок
Всем привет!

Вообщем есть скрипт который загружается на каждой странице и проверяется куки, если куки есть и они активны (срок годности не прошел - эта дата записывается в БД, чтобы не смогли подделать дату куки) то установить переменную $auth = "1"; а дальше на каждой странице сайта где это нужно, проверять если $auth = "1"; тогда вывести информацию как для авторизованного


Вот скрипт авторизации:

PHP:
if (isset($_POST['login']))
    $login = mb_strtolower($_POST['login']);
if (isset($_POST['password']))
    $password = $_POST['password'];

$last_login_ip = mysqli_real_escape_string($db_connection, ip2long(getRealIpAddr())) ;
$last_login_user_agent = mysqli_real_escape_string($db_connection, $_SERVER['HTTP_USER_AGENT']) ;

$fail = validate_login($login);
if ($fail == "")
{
    $login = mysqli_real_escape_string($db_connection, $login) ;
    $query = "SELECT login  FROM users WHERE  login='$login'";
    $result = mysqli_query($db_connection, $query) or die(mysqli_error($db_connection));
    $row_count = mysqli_num_rows($result);
    if ($row_count < 1)
    {
        $fail = "Неверный логин или пароль. <br />";
    }
}
if ($fail == "")
{
    $query = "SELECT id, login, hash FROM users WHERE  login='$login' LIMIT 1";
    $result = mysqli_query($db_connection, $query) or die(mysqli_error($db_connection));
    $row = mysqli_fetch_assoc($result);
    //     var_dump($row);
    $hash_current = $row ['hash'];
    if (password_verify($password, $hash_current))
    {

        $key_cookie = generateSalt();
        $cookie = md5($login . $key_cookie);

        $query = "UPDATE users
        SET last_login_datetime=CURRENT_TIMESTAMP(), last_login_user_agent='$last_login_user_agent', cookie='$cookie'
WHERE login = '$login'";
        $result = mysqli_query($db_connection, $query) or die(mysqli_error($db_connection));

        $_SESSION['login'] = $login;
        $_SESSION['logged'] = "1";
        $log_ok = "1";

        setcookie ("login", $login, time() + 120 ); // ставлю куки на 2 минуты пока для теста
        setcookie ("cookie", $cookie, time() + 120 ); // ставлю куки на 2 минуты пока для теста

        $log_ok_text = "$login, Авторизация прошла успешно. Вернуться на <a href='$site_url/index.php' >Главную</a>

 " ;

    }
    else
    {
        $fail = "Неверный логин или пароль. <br />";

        $text_to_log = "$login введен неверный пароль";
    }
}

    if(isset($_POST['log']))
    {
        $fail2 = "<tr><td colspan='2'>В вашей форме найдены следующие ошибки:<br> <p><font color=red size='1'><i> $fail
</i></font></p></td></tr>
";

    }
    else
    {
        $fail2 = "";
    }

    require 'header.php';
// дальше идет html код


А вот скрипт проверки куки\авторизации:

PHP:
<?php
//$auth = "0"; // авторизован 1, нет 0

if (isset($_COOKIE['login']) AND isset($_COOKIE['cookie']))

{
    $session_login = $_COOKIE['login'];
    $session_cookie = $_COOKIE['cookie'];

    $query = " SELECT id, login, cookie, last_login_datetime FROM users WHERE login='$session_login' LIMIT 1";
    $result = mysqli_query($db_connection, $query) or die(mysqli_error($db_connection));
    $row = mysqli_fetch_array($result);
    if (mysqli_num_rows($result) > 0)
    {
        if (
            $row['cookie'] === $session_cookie AND (   ( ($row['last_login_datetime'])+120 ) > CURRENT_TIMESTAMP()  )
        )
        {
            $login = $row['login'];
            $key_cookie = generateSalt();
            $cookie = md5($login . $key_cookie);
            $query = "UPDATE users
        SET last_login_datetime=CURRENT_TIMESTAMP(), cookie='$cookie'
WHERE login = '$login'";

            $query = " SELECT id, login, cookie FROM users WHERE login='$session_login' LIMIT 1";
            $result = mysqli_query($db_connection, $query) or die(mysqli_error($db_connection));
            $row = mysqli_fetch_array($result);
            setcookie ("login", $row['login'], time() + 120 );// продлеваю куки на 2 минуты пока для теста
            setcookie ("cookie", $row['cookie'], time() + 120 );// продлеваю куки на 2 минуты пока для теста
            $auth = "1";
        }
        else
        {
            header('Location: '. $site_url . "/index.php?s=logout");

        }
    }


}
else
{
    $auth = "0";
}


?>
Каждый раз при авторизации и при открытии любой странице,
last_login_datetime обновляется в базе в формате 2021-11-17 10:58:46
в поле cookie записывается хэш который сравнивается с хэшем из БД.

Что хочу сделать: Каждый раз при открытии любой странице скрипт авторизации проверяет, есть ли у данного login куки, смотрит куки в базе и плюс проверяет срок установки последний раз куки по полю last_login_datetime. Например для теста установить хочу 2 минуты срок годности куки.
Вот в таком виде не работает сравнение, как правильно сравнивать срок установки куки, если например мне надо сделать срок жизни 2 минуты (для теста)
PHP:
if (
            $row['cookie'] === $session_cookie AND (   ( ($row['last_login_datetime'])+120 ) > CURRENT_TIMESTAMP()  )
        )
После чего на каждой странице сайта где необходимо, буду проверять переменную $auth 0 она или 1, и выводить соответствующую разную инфу в зависимости от того авторизован ли пользователь. Если срок годности прошел, то отправить пользователя на страницу /index.php?s=logout для обнуления куки и необходимости авторизоваться еще раз.
Как правильно сделать проверку срока годности куки сравнивая из БД?
 

ImperatorR

Новичок
Изменил скрипт проверки авторизации
PHP:
<?php
 
//$auth = "0"; // авторизован 1, нет 0
 
if (isset($_COOKIE['login']) and isset($_COOKIE['cookie']))
{
    $session_login = fix_security($_COOKIE['login']);
    $session_cookie = fix_security($_COOKIE['cookie']);
 
    $query = " SELECT id, login, cookie, last_login_datetime FROM users WHERE login='$session_login' LIMIT 1";
    $result = mysqli_query($db_connection, $query) or die(mysqli_error($db_connection));
    $row = mysqli_fetch_array($result);
    if (mysqli_num_rows($result) > 0)
    {
        $last_login_datetime = $row['last_login_datetime'];
        $last_login_datetime = strtotime('$last_login_datetime + 2 minutes');
        $current_datetime = strtotime(date('Y-m-d H-i-s', time()));
        if (
          $row['cookie'] = $session_cookie and ($last_login_datetime  > $current_datetime )
        )
        {
            $login = $row['login'];
            $key_cookie = generateSalt();
            $cookie = md5($login . $key_cookie);
            $query = "UPDATE users
        SET last_login_datetime=CURRENT_TIMESTAMP(), cookie='$cookie'
WHERE login = '$login'";
 
            $query = " SELECT id, login, cookie FROM users WHERE login='$session_login' LIMIT 1";
            $result = mysqli_query($db_connection, $query) or die(mysqli_error($db_connection));
            $row = mysqli_fetch_array($result);
            setcookie("login", $row['login'], time() + 120);
            setcookie("cookie", $row['cookie'], time() + 120);
            $auth = "1";
        } else
        {
            header('Location: ' . $site_url . "/index.php?s=logout");
 
        }
    }
 
 
} else
{
    $auth = "0";
}
Вроде куки ставит но в базу почему то не обновляет при открытии страниц
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Мне вот дюже интересно что же там в fix_security()...
 

Valick

Новичок
90% "мануалов" это копипаста друг у друга, причём аля "привет 90-е"
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
В данном случае вышеотписавшийся имел в виду тот факт, что надо использовать подготовленные запросы, они же prepared statements, например https://phpdelusions.net/mysqli_examples/select
 

ImperatorR

Новичок
А для чего это надо, не совсем понимаю?
Сейчас почти прочитал 3 книги по php mysql, так же мануалы из инета смотрю, везде пишут процедурным стилем.
Что плохого?
Сайтом пользуются всего лишь 20 человек, мои знакомые
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
процедурный стиль не при чем, тебе надо понять, что если у тебя в переменной встретится кавычка " или еще какой "спецсимвол" или их последовательность -
твой запрос - $query = " SELECT id, login, cookie, last_login_datetime FROM users WHERE login='$session_login' LIMIT 1";
- в лучшем случае вызовет ошибку.
 

ImperatorR

Новичок
процедурный стиль не при чем, тебе надо понять, что если у тебя в переменной встретится кавычка " или еще какой "спецсимвол" или их последовательность -
Все данные которые вставляю обрабатываю через mysqli_real_escape_string
 

AnrDaemon

Продвинутый новичок
Все данные которые вставляю обрабатываю через mysqli_real_escape_string
Тебе предлагают выкинуть из твоего кода мусор и писать меньше кода с бОльшим эффектом, но ты упёрся и твердишь "ну у меня же!!!"
Ну может хватит уже тупить и упираться?

И если на то пошло, раз уж ты разрабатываешь систему с нуля, почитай https://phpdelusions.net/pdo#why
После чего можно посмотреть на https://phpdelusions.net/pdo_examples/password_hash и потом https://phpdelusions.net/pdo/mysqli_comparison
 

AmdY

Пью пиво
Команда форума
Да и зачем эта морока с куками непонятно. Почему не используете сесси?
 

AmdY

Пью пиво
Команда форума
использую щас их, но у них срок годности маленький же, понятно что можно это увеличить значение с 24 минут, но это вроде не лучшая практика?
Это как раз нормальная практика
Плюс это добавит безопасности.
Советую ещё и про куки доку почитать, обратить внимание на флаг httponly для той же безопасности.

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

ImperatorR

Новичок
благодарю)

И главное, не надо на каждый запрос лазить в базу данных, достаточно просто ставить флаг в сессию и затем проверять его.
Что то вроде этого $_SESSION['logged'] = "1" ?
Когда пользователь вводит логин и пароль, и если пароль верный, то установить в сессию переменную Login которую ввел пользователь, и взять из базы $row ['email'] и установить ее так же в сессию (использую это дальше в скрипте)
PHP:
        $_SESSION['login'] = $login;
        $_SESSION['email'] = $row ['email'];
        $_SESSION['logged'] = "1";
Сейчас у меня в закрытых разделах такая проверка стоит:
PHP:
if (  !isset($_SESSION['login']) AND !isset($_SESSION['email'])  )

{
    header("Location: $site_url/index.php?s=login");
}

else
{
... //код для закрытого раздела
}
Это ведь норм?
 

AmdY

Пью пиво
Команда форума
тип того. только после header нужно писать exit, чтобы скрипт остановился. а то сам по себе хедер этого не делает
 
Сверху