在登录脚本中放置password_verify的位置?

时间:2015-09-13 20:10:33

标签: php session pdo password-encryption login-script

另一个晚上,另一个问题!

我已经创建了一个登录页面,如果密码是纯文本,它可以正常工作。

我遇到的问题是我的注册表单使用password_hash为表输入加密密码。

我目前的脚本如下。

  

注册脚本

$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
  

登录脚本

<?php
session_start();
    if(isset($_POST['email'], $_POST['password'])){
        require('../../../private_html/db_connection/connection.php');
        $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
        $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

        $query = $conn->prepare("SELECT * FROM user_accounts WHERE email=:email AND password=:password");
        $query->bindParam(':email', $_POST['email']);
        $query->bindParam(':password', $_POST['password']);
        $query->execute();

        if($row = $query->fetch()){
            $_SESSION['email'] = $row['email'];
            $_SESSION['first_name'] = $row['first_name'];
            header("Location: ../../myaccount/myaccount.php");
        }
        else {header("Location:../../login/login.php ");}
    }

?>

我对此有几个问题:

  1. 我在哪里将password_verify放入我的登录脚本?
  2. 我不必输入多个$_SESSION['xxx'] = $row['xxx'];来在“我的帐户”页面上显示用户详细信息,而是如何利用我所阅读的$results = $stmt->fetch(PDO::FETCH_ASSOC);方法?
  3. 非常感谢,

    CyrilWalrus

2 个答案:

答案 0 :(得分:12)

之前您已阅读代码,请注意代码中的Fake Registration阻止,但有必要向您展示,端至端

<?php
session_start();
    // Begin Vault
    // credentials from a secure Vault, not hard-coded
    $servername="localhost";
    $dbname="login_system";
    $username="dbUserName";
    $password="dbPassword";
    // End Vault

    // The following two variables would come from your form, naturally
    // as $_POST[]
    $formEmail="jsmith123@gmail.com";
    $ctPassword="¿^?fish╔&®)";  // clear text password

    try {
        #if(isset($_POST['email'], $_POST['password'])){
        #require('../../../private_html/db_connection/connection.php');
        $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
        $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

        // Begin Fake Registration
        //   fake it that user already had password set (from some registration insert routine)
        //   the registration routine had SSL/TLS, safely passing bound parameters.
             $hp=password_hash($ctPassword,PASSWORD_DEFAULT); // hashed password, using 
             $conn->query("delete from user_accounts where email='jsmith123@gmail.com'");
             $conn->query("insert user_accounts(first_name,last_name,email,password) values ('joe','smith','jsmith123@gmail.com','$hp')");
        //   we are done assuming we had a registration for somewhere in your system
        // End Fake Registration

        $query = $conn->prepare("SELECT * FROM user_accounts WHERE email=:email");
        $query->bindParam(':email', $formEmail);
        $query->execute();

        unset($_SESSION['email']);
        unset($_SESSION['first_name']);

        if(($row = $query->fetch()) && (password_verify($ctPassword,$row['password']))){
            $_SESSION['email'] = $row['email'];
            $_SESSION['first_name'] = $row['first_name'];
            //header("Location: ../../myaccount/myaccount.php");
            echo "hurray, you authenticated.<br/>";
        }
        else {
            //header("Location:../../login/login.php ");
            echo "invalid login<br/>";
        }
        #}
    } catch (PDOException $e) {
        echo 'Connection failed: ' . $e->getMessage();
        exit();
    }
?>

浏览器输出:

  

欢呼,你认证了。

注意,password_hash()函数使用随机盐,很明显 如果您运行多次,使用带有相同clearText输入的散列密码更改,例如这些散列密码:

$2y$10$KywNHrGiPaK9JaWvOrc8UORdT8UXe60I2Yvj86NGzdUH1uLITJv/q

$2y$10$vgJnAluvhfdwerIX3pAJ0u2UKi3J.pfvd0vIqAwL0Pjr/A0AVwatW

这两个都是后面提到的相同明文密码的哈希结果。 salt和哈希cost被烘焙到哈希密码中并保存。这些电话都可以在下面的链接中阅读。

来自手册password_hashpassword_verify

模式

create table user_accounts
(   id int auto_increment primary key,
    first_name varchar(50) not null,
    last_name varchar(50) not null,
    email varchar(100) not null,
    password varchar(255) not null
);

答案 1 :(得分:-3)

$query = $conn->prepare("SELECT * FROM user_accounts WHERE email=?");
$query->execute([$_POST['email']]);

if($row = $query->fetch() && password_verify($_POST['password'], $row['password'])){
    $_SESSION['user'] = $row;