首页 > 解决方案 > 即使凭据不正确,PHP 中的会话变量也允许我登录

问题描述

我有一个关于会话的问题。当我测试我的 PHP 代码时,我注意到了一些不寻常的事情。基本上,我有两门课程,证书存储在他们自己的数据库中。

因此,下面的代码确定了各个课程的登录名(每门课程的代码完全相同,不同之处在于数据库表)

<?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"]) && $_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) && 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。

缺点

所以这很不寻常,我想知道如何解决这个问题,并更多地了解会话,因为我认为它与此相关。

更新

我还发现用户名是否不同并不重要。它可能正在识别用于两次登录的相同密码。

标签: php

解决方案


身份验证从未在选项卡 2 中实际执行。因为您已经有一个会话,所以当您点击此代码块时,您将被重定向到索引:

// Check if the user is already logged in, if yes then redirect him to welcome page 
if(isset($_SESSION["loggedin"]) && $_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"]) && $_SESSION["loggedin"] === true && $_SESSION["authenticated_from"]==="flitpcusers"){ 
  header("location: index");    
  exit; 
}

这将防止表 1 认证的会话被识别为表 2 会话。

虽然以上将解决您观察到的奇怪行为,但我真的会在这里重新设计您的数据库方案。奇怪的是,我需要为不同的课程进行不同的身份验证。理想情况下,我进行一次身份验证,并且该身份验证用于该身份下的任何/所有服务。看看谷歌:我不必先登录 Youtube,然后登录 Gmail,然后登录搜索,我只需登录一次,然后谷歌服务器就会确定我可以访问哪些服务。


推荐阅读