PHP准备语句登录

PHP准备语句登录,php,mysql,login,passwords,sql-injection,Php,Mysql,Login,Passwords,Sql Injection,我正在将密码散列和SQL注入防御添加到登录系统中。目前,我遇到了一个错误 <?php session_start(); //start the session for user profile page define('DB_HOST','localhost'); define('DB_NAME','test'); //name of database define('DB_USER','root'); //mysql user define('DB_PASSWORD','')

我正在将密码散列和SQL注入防御添加到登录系统中。目前,我遇到了一个错误

    <?php
session_start(); //start the session for user profile page

define('DB_HOST','localhost'); 
define('DB_NAME','test'); //name of database
define('DB_USER','root'); //mysql user
define('DB_PASSWORD',''); //mysql password

$con = new PDO('mysql:host=localhost;dbname=test','root','');

function SignIn($con){
    $user = $_POST['user']; //user input field from html
    $pass = $_POST['pass']; //pass input field from html
    if(isset($_POST['user'])){ //checking the 'user' name which is from Sign-in.html, is it empty or have some text
        $query = $con->prepare("SELECT * FROM UserName where userName = :user") or die(mysqli_connect_error());
        $query->bindParam(':user',$user);
        $query->execute();

        $username = $query->fetchColumn(1);
        $pw = $query->fetchColumn(2);//hashed password in database
        //check username and password
        if($user==$username && password_verify($pass, $pw)) {
            // $user and $pass are from POST
            // $username and $pw are from the rows

            //$_SESSION['userName'] = $row['pass'];
            echo "Successfully logged in.";
        }

        else { 
            echo "Invalid."; 
        }
    }
    else{
        echo "INVALID LOGIN";
    }
}

if(isset($_POST['submit'])){
    SignIn($con);
}
?>

在上面的代码中,当我输入有效的用户名和密码时,系统会打印出“Invalid”。这可能是if语句中密码_verify()中的错误(因为如果删除它,我将成功登录)。我很确定我已经正确地准备、绑定和执行了查询?有人知道它为什么这样做吗

谢谢

使用

// it will be an array('name' => 'John', 'password_hash' => 'abcd')
// or FALSE if user not found
$storedUser = $query->fetch(PDO::FETCH_ASSOC);
而不是

$username = $query->fetchColumn(1);
$pw = $query->fetchColumn(2);
因为fetchColumn会移动结果的光标。所以第一个调用提取第一行的1列,第二个调用将从第二行提取数据

使用

// it will be an array('name' => 'John', 'password_hash' => 'abcd')
// or FALSE if user not found
$storedUser = $query->fetch(PDO::FETCH_ASSOC);
而不是

$username = $query->fetchColumn(1);
$pw = $query->fetchColumn(2);
因为fetchColumn会移动结果的光标。所以第一个调用提取第一行的1列,第二个调用将从第二行提取数据

使用

// it will be an array('name' => 'John', 'password_hash' => 'abcd')
// or FALSE if user not found
$storedUser = $query->fetch(PDO::FETCH_ASSOC);
而不是

$username = $query->fetchColumn(1);
$pw = $query->fetchColumn(2);
因为fetchColumn会移动结果的光标。所以第一个调用提取第一行的1列,第二个调用将从第二行提取数据

使用

// it will be an array('name' => 'John', 'password_hash' => 'abcd')
// or FALSE if user not found
$storedUser = $query->fetch(PDO::FETCH_ASSOC);
而不是

$username = $query->fetchColumn(1);
$pw = $query->fetchColumn(2);

因为fetchColumn会移动结果的光标。所以第一个调用提取第一行的1列,第二个调用将从第二行提取数据

您正在执行SELECT*,并使用fetchColumn,因此结果取决于返回的列顺序。您应该选择所需的特定列,或者将整行作为关联数组提取,并按列名访问它

还有两个问题需要解决:

  • 在使用PDO时,不应该使用mysqli_connect_error()。正确的功能应该是
  • 您正在使用连接设置定义一些常量,但在PDO()调用中不使用它们,而是重复这些值

您正在执行SELECT*,并使用FETCHTCOLUMN,因此结果取决于返回的列顺序。您应该选择所需的特定列,或者将整行作为关联数组提取,并按列名访问它

还有两个问题需要解决:

  • 在使用PDO时,不应该使用mysqli_connect_error()。正确的功能应该是
  • 您正在使用连接设置定义一些常量,但在PDO()调用中不使用它们,而是重复这些值

您正在执行SELECT*,并使用FETCHTCOLUMN,因此结果取决于返回的列顺序。您应该选择所需的特定列,或者将整行作为关联数组提取,并按列名访问它

还有两个问题需要解决:

  • 在使用PDO时,不应该使用mysqli_connect_error()。正确的功能应该是
  • 您正在使用连接设置定义一些常量,但在PDO()调用中不使用它们,而是重复这些值

您正在执行SELECT*,并使用FETCHTCOLUMN,因此结果取决于返回的列顺序。您应该选择所需的特定列,或者将整行作为关联数组提取,并按列名访问它

还有两个问题需要解决:

  • 在使用PDO时,不应该使用mysqli_connect_error()。正确的功能应该是
  • 您正在使用连接设置定义一些常量,但在PDO()调用中不使用它们,而是重复这些值


为什么不在DB级别验证密码?@chris85 afaik MySQL无法验证Bcrypt。$pass的值是否符合您的预期?创建密码时数据库是否保存哈希?不确定Bcrypt是什么,但在将其发送到数据库之前使用它。类似于
$pass=bcrypt($_POST['pass'])//从html传递输入字段
@chris85 Bcrypt是PHP中密码存储的默认和推荐哈希例程。以前不能这样做,因为每次散列时,它都会生成一个唯一的盐,作为散列的一部分存储。您需要获取散列并根据用户发布的内容进行验证。为什么不在DB级别验证密码?@chris85 afaik MySQL无法验证Bcrypt。$pass的值是否符合您的预期?创建密码时数据库是否保存哈希?不确定Bcrypt是什么,但在将其发送到数据库之前使用它。类似于
$pass=bcrypt($_POST['pass'])//从html传递输入字段
@chris85 Bcrypt是PHP中密码存储的默认和推荐哈希例程。以前不能这样做,因为每次散列时,它都会生成一个唯一的盐,作为散列的一部分存储。您需要获取散列并根据用户发布的内容进行验证。为什么不在DB级别验证密码?@chris85 afaik MySQL无法验证Bcrypt。$pass的值是否符合您的预期?创建密码时数据库是否保存哈希?不确定Bcrypt是什么,但在将其发送到数据库之前使用它。类似于
$pass=bcrypt($_POST['pass'])//从html传递输入字段
@chris85 Bcrypt是PHP中密码存储的默认和推荐哈希例程。以前不能这样做,因为每次散列时,它都会生成一个唯一的盐,作为散列的一部分存储。您需要获取散列并根据用户发布的内容进行验证。为什么不在DB级别验证密码?@chris85 afaik MySQL无法验证Bcrypt。$pass的值是否符合您的预期?创建密码时数据库是否保存哈希?不确定Bcrypt是什么,但在将其发送到数据库之前使用它。类似于
$pass=bcrypt($_POST['pass'])//从html传递输入字段
@chris85 Bcrypt是PHP中密码存储的默认和推荐哈希例程。以前不能这样做,因为每次散列时,它都会生成一个唯一的盐,作为散列的一部分存储。您需要获取散列并根据用户发布的内容进行验证。这是一个很好的建议,但绝不是一个好建议