繁体   English   中英

刷新后登录会话被破坏

[英]login session destroyed after refresh

我已经在Google的一些帮助下完成了登录脚本,但问题是每次我刷新页面时,它都会注销并重定向到登录页面。 因此,基本上,我希望用户输入详细信息后登录,并且一次刷新后不注销。 我的代码是:

<?php

if(!isset($_SESSION)){
session_start();
}

$username = mysqli_real_escape_string($con, $_POST['username']);
$password = mysqli_real_escape_string($con, $_POST['password']);

if ($username && $password)

{


$result = mysqli_query($con, "SELECT * FROM admin WHERE username='$username' ");

$numrows = mysqli_num_rows($result);

if($numrows !=0)
{
    while($row = mysqli_fetch_assoc($result))
    {
        $dbusername = $row["username"];
        $dbpassword = $row["password"]; 

    }
        if($username==$dbusername && $password==$dbpassword)
        {

            $_SESSION['username'] = $dbusername;
        }
        else
            echo "Incorrect Password";
}       
else
    header("location: login.php"); 


}
else    
header("location: login.php"); 
?>

mysqli_real_escape_string() 要求您必须将数据库的主动/建立的连接。 由于在连接之前正在执行m_r_e_s()调用,因此只需返回布尔FALSE即可表示失败。 因此,您浪费了“引用”值。

插入字符串中的布尔假值只会转换为空字符串,因此查询看起来像

SELECT ... WHERE username=''
                           ^---see the boolean false in there?

您的代码序列应为:

session_start();
connect_to_db();
prepare_variables();
do_query();

而且由于您使用的是mysqli,为什么仍要手动转义变量? 您可以只使用准备好的语句+占位符,然后完全绕开该问题。

学习要点1:会议

这里有一些与会议有关的学习要点,以及如何有效地使用它们。 请注意,您代码的问题是您在询问是否在调用会话开始之前设置了会话,因此超全局$ _SESSION不可用,因此您的逻辑语句始终返回false,除非您在登录时调用会话开始时无论如何都不要调用会话开始。 在配置文件中调用会话开始1次(请确保在所有“视图/页面”中都包含此文件,然后您可以检查会话是否设置为正常。请仔细阅读此代码并尝试了解其所做的一切这样您就可以利用php会话提供的功能。

添加到login.php

//upon successful validation of login.
//create an object to store basic user information in. 

$user = (object) ['username'=>$username,'hash_password'=>$password,'group'=>$usergroup,'site_secret'=>$secret];//your user object

$_SESSION['user'] = $user;//store the object in the users session.

添加到您的config.php或所有页面中包含的任何文件

GLOBAL const static $secret = (string)'someUltraSecretStringThatIsDifficultToGuess';//your site wide secret.(you should probably add this to your config file instead of the login.
session_start(); 

//you have to call session start or you don't have access to $_SESSION superglobal, 
//regardless of a user being logged in or logged out they have a session.
//as a programmer it is your job to figure out how to store data in the session

if(isset($_SESSION['user']) && is_object($_SESSION['user']) && $_SESSION['user']->site_secret == $secret)
{
    $loggedInUser = $_SESSION['user'];//if an authenticaed user session is set and is an object and contains our site secret, we assign the $loggedInUser variable to it. so we can call this variable instead of calling the session ad nauseum in our code.
}

现在在文件中以测试用户是否已登录

if($loggedInUser !== null && is_object($loggedInUser) && $loggedInUser->site_secret = $secret)
{
    //user is logged in. no reason to even call the database at this point, unless there is extra information you need.
    //if said information is going to be accessed on multiple pages, its probably wise to include it in the object when you create it during the login process. don't store overly sensitive
    //information in the object in any circumstance. things like credit card numbers, plain text passwords, security questions are big no nos.
}

现在,如果您需要从函数内部调用此对象,则有两种方法

//pass by reference

function foo($loggedInUser) 
{
    //your object is available here because you passed by reference! 
    //you can check if a user is loggedIn from within functions now without a single call to the database!
}

//pass with global language feature.
function bar()
{
    global $loggedInUser; //object is available here through usage of global directive. nifty eh?
}

其他考虑

考虑将站点范围的机密属性添加到您的loggingInUser对象中,并检查此机密是否存在以标识有效会话。 如果未通过传递格式错误的get请求来登录用户,则可以创建一个名为$ loggedInUser的变量。 很有可能攻击者无法猜测您的站点秘密。 在第一个示例中显示了此站点范围秘密的示例。

学习要点#2:面向对象的Mysqli速成班

创建连接对象。

$mysqli = new mysqli("db-host","db-username","db-password","db-name");

设置字符集

//since your object is already created, you can now set a property on the object

$mysqli->set_charset("utf8");//set it to whatever the collation of your database is.

//side note: you should user utf_unicode_ci in your database and utf8 in php.

运行查询

$query = $mysqli->query("SELECT column1,column2,column3 FROM table1 WHERE 1 LIMIT 30");

//getting number of rows
$num_rows = $query->num_rows;//your mysqli object has morphed into $query at this point.

//working with the result set
if($num_rows > 0)
{
    while($row = $query->fetch_assoc())
    {
    echo '<li>'.$row["column1"].' | '.$row["column2"].' | '.$row["column3"].'</li>';
    }
    $query->close();//optionally close the query object NOTE: the $mysqli object is still open
    $query->free();//optionally free the result set
}
//when you are done with your $mysqli object close the connection
$mysqli->close();

准备好的语句:手动转义值的替代方法

$stmt = $mysqli->prepare("SELECT column1,column2,column3 FROM table1 WHERE column4 = ? column5 = ? and column6 = ?");//prepare our query.

//now we need to assign our variables to the question marks in the statement above in the correct order.
// s represents string, d represents double and i represents an integer.
$stmt->bind_param('sdi',$column4,$column5,$column6);//for illustrative purposes i name the variables the same as the column they correspond to so you can understand.

//now that we have bound our parameters to our statement wehave to execute it. if it doens't execute there is an error in our query or binding parameters

if($stmt->execute())
{
    //now we have two ways we can work with this result set. i am only going to show you what i consider the best way, `bind_result().
    $stmt->bind_result($column1,$column2,$column3);//binds in the same order of our columns.
    if($stmt->num_rows > 0) {
        //great, our query returned a result! lets work with this data now
        while($stmt->fetch())
        {
            echo '<li>'.$column1.' | '.$column2.' | '.$column3.'</li>';//we prent each row of our result. easy peasy
        }
        $stmt->close();//no need to free the result, as it is not stored by default.
    }
    //if there were no results, no need to close stmt as it was automatically closed by default.    
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM