Переменная сеанса в PHP позволяет мне входить в систему, даже если учетные данные неверны

#php

#php

Вопрос:

У меня вопрос о сеансах. Я заметил кое-что необычное, когда тестировал свой PHP-код. В принципе, у меня есть два курса, и учетные данные хранятся в их собственной базе данных.

  • Пример: Курс 1: Имя пользователя: abc Пароль: 123, таблица базы данных: flitpc
  • Пример: Курс 2: Имя пользователя: abc Пароль: 999, таблица базы данных: itst

Итак, приведенный ниже код определяет логин для соответствующих курсов (оба точно таких же кода для каждого курса, с разницей в таблице базы данных)

 <?php   
// Initialize the session   
session_start();    
    
// Check if the user is already logged in, if yes then redirect him to welcome page 
if(isset($_SESSION["loggedin"]) amp;amp; $_SESSION["loggedin"] === true){ 
  header("location: index");    
  exit; 
}   
    
// Include config file  
require_once "config.php";  
    
// Define variables and initialize with empty values    
$username = $password = ""; 
$username_err = $password_err = ""; 
    
// Processing form data when form is submitted  
if($_SERVER["REQUEST_METHOD"] == "POST"){   
    
    // Check if username is empty   
    if(empty(trim($_POST["username"]))){    
        $username_err = "Please enter username";    
    } else{ 
        $username = trim($_POST["username"]);   
    }   
        
    // Check if password is empty   
    if(empty(trim($_POST["password"]))){    
        $password_err = "Please enter your password";   
    } else{ 
        $password = trim($_POST["password"]);   
    }   
        
    // Validate credentials 
    if(empty($username_err) amp;amp; empty($password_err)){   
        // Prepare a select statement   
        $sql = "SELECT id, username, password FROM flitpcusers WHERE username = ?"; 
            
        if($stmt = mysqli_prepare($link, $sql)){    
            // Bind variables to the prepared statement as parameters   
            mysqli_stmt_bind_param($stmt, "s", $param_username);    
                
            // Set parameters   
            $param_username = $username;    
                
            // Attempt to execute the prepared statement    
            if(mysqli_stmt_execute($stmt)){ 
                // Store result 
                mysqli_stmt_store_result($stmt);    
                    
                // Check if username exists, if yes then verify password    
                if(mysqli_stmt_num_rows($stmt) == 1){                       
                    // Bind result variables    
                    mysqli_stmt_bind_result($stmt, $id, $username, $hashed_password);   
                    if(mysqli_stmt_fetch($stmt)){   
                        if(password_verify($password, $hashed_password)){   
                            // Password is correct, so start a new session  
                            session_start();    
                                
                            // Store data in session variables  
                            $_SESSION["loggedin"] = true;   
                            $_SESSION["id"] = $id;  
                            $_SESSION["username"] = $username;                              
                                
                            // Redirect user to welcome page    
                            header("location: index.php");  
                        } else{ 
                            // Display an error message if password is not valid    
                            $password_err = "The password you entered was not valid";   
                        }   
                    }   
                } else{ 
                    // Display an error message if username doesn't exist   
                    $username_err = "No account found with that username";  
                }   
            } else{ 
                echo "Oops! Something went wrong. Please try again later."; 
            }   
            // Close statement  
            mysqli_stmt_close($stmt);   
        }   
    }   
        
    // Close connection 
    mysqli_close($link);    
}   
?>
  

Итак, вот в чем дело: в моем браузере открыты обе вкладки: 1 для курса 1, другая для курса 2.

Дефект

  • Вкладка 1: я вхожу в курс 1 с его учетными данными, работает нормально, я не выхожу из системы.

  • Вкладка 2: я вхожу в курс 2 с именем пользователя курса 2 (тем же именем пользователя, что и в курсе 1), но я также использую пароль курса 1, он регистрирует меня,

  • Теперь, если я выхожу из обоих курсов и повторяю второй пункт выше, я не могу войти в систему.

Так что это необычно, и я хочу знать, как это исправить, и немного больше узнать о сеансах, поскольку я думаю, что это связано с этим.

Обновить

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

Комментарии:

1. на первый взгляд, вы не очищаете сеанс $_SESSION["loggedin"] = false; при неправильном входе в систему или выходе из системы

2. Хммм. У меня есть logout.php файл, в котором, если пользователь выходит из системы, сеанс уничтожается, что является следующим: <?php // Initialize the session session_start(); // Unset all of the session variables $_SESSION = array(); // Destroy the session. session_destroy(); // Redirect to login page header("location: login"); exit; ?>

3. Но я проверю, чтобы это $SESSION[Loggedin"] было ясно. Я предполагаю, что вы имеете в виду уничтожение сеанса с помощью session_destroy() ? Я только что попытался поместить это в оператор else, следующий из $_SESSION{"loggedIn"].. . если оператор, но не повезло.

Ответ №1:

Аутентификация фактически никогда не выполняется на вкладке 2. Поскольку у вас уже есть сеанс, вы перенаправляетесь на индекс, когда нажимаете на этот блок кода:

 // Check if the user is already logged in, if yes then redirect him to welcome page 
if(isset($_SESSION["loggedin"]) amp;amp; $_SESSION["loggedin"] === true){ 
  header("location: index");    
  exit; 
} 
  

Вам нужно course где-то сохранить $_SESSION и проверить, существует ли соответствующий сеанс не только, но и соответствует курсу, в противном случае аутентификация с использованием учетных данных таблицы 1 неотличима от аутентификации с использованием учетных данных таблицы 2.

Редактировать:

После аутентификации сохраните, откуда произошла аутентификация:

 // Store data in session variables  
$_SESSION["loggedin"] = true;   
$_SESSION["id"] = $id;  
$_SESSION["username"] = $username; 
$_SESSION["authenticated_from"] = "flitpcusers";
  

Затем, когда вы проверяете, существует ли $_SESSION, также проверьте, подходит ли он для соответствующего курса, поэтому:

 // Check if the user is already logged in, if yes then redirect him to welcome page 
if(isset($_SESSION["loggedin"]) amp;amp; $_SESSION["loggedin"] === true amp;amp; $_SESSION["authenticated_from"]==="flitpcusers"){ 
  header("location: index");    
  exit; 
}
  

Это предотвратит распознавание аутентифицированного сеанса таблицы 1 как сеанса таблицы 2.

Хотя вышеизложенное исправит странное поведение, которое вы наблюдаете, я бы действительно посмотрел на перепроектирование вашей схемы базы данных здесь. Странно, что мне нужно проходить аутентификацию по-разному для разных курсов. В идеале я аутентифицируюсь один раз, и эта аутентификация используется для любых / всех служб под этим идентификатором. Посмотрите на Google: мне не нужно входить на Youtube, затем входить в Gmail, затем входить в поиск, я вхожу в систему один раз, а затем серверы Google определяют, к каким службам у меня есть доступ.

Комментарии:

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

2. Хм .. попробовал несколько вещей, но все еще не работает, интересно, будет ли лучше, если я смогу увидеть фрагмент кода о том, что вы называете руководством 🙂

3. Потрясающе, это сработало. Большое вам спасибо. Я понимаю с вашей точки зрения (я не писал оригинальный дизайн этого). Дело в том, что мы продаем курсы по отдельности, и каждый курс имеет свой собственный доступ для пользователя. Поэтому я не хотел, чтобы пользователь мог приобрести один курс, но затем мог использовать свои учетные данные для другого курса.

4. Кроме того, рассмотрите возможность настройки переменных сеанса для хранения аутентификации (и другой информации) специально для требуемого курса. Например, вместо $_SESSION[‘loggedin’] измените ссылки на $_SESSION[‘flitpcusers’][‘loggedin’] (как при назначении, так и при проверке переменных). Это позволит вам иметь несколько приложений / курсов, работающих по одному и тому же корневому URL. Это также позволит пользователям одновременно входить в два разных курса без постоянной перезаписи информации о сеансе друг друга (не уверен, что это требование).

Ответ №2:

Вы должны использовать два разных браузера. Не тот браузер.
Поскольку браузер проводит сеанс по уважаемому веб-адресу, он не определяет, сколько у вас вкладок, все вкладки будут отправлять один и тот же идентификатор сеанса.
Предположим, что вы вошли в браузер Google Chrome, открыли другую вкладку и попали на тот же веб-адрес, тогда браузер отправит запрос на сервер с тем же идентификатором сеанса, и вы войдете в систему автоматически, потому что сеанс уже существует.

Комментарии:

1. Да, но это два разных курса, у них два разных URL.

2. Вы имеете в виду, что базовый URL-адрес совершенно другой? Можете ли вы дать две ссылки?

3. Да, две ссылки: metis-online.com/itst-998372318/login и metis-online.com/flitpc-998372319/login

4. Похоже, что ваши базовые URL-адреса совпадают, что metis-online.com таким образом, вы не можете войти в систему с той же переменной сеанса в том же браузере. Вы можете изменить имя индекса сеанса для входа в разные таблицы, иначе вам придется использовать другой браузер.

5. Можете ли вы показать мне с помощью кода, что вы подразумеваете под своим последним комментарием, таблицы индекса сеанса. Один курс указывает на таблицу, известную как ‘flitpc’, а другой ‘itst’ (просмотр SQL-запроса в ответе в качестве примера)