0

単純なログインシステムを作成しようとしていますが、ユーザーが指定したユーザー名がデータベースに存在するかどうかをクエリしていますが、行数を取得するのに問題があります。未定義の変数num:errorを取得し続けます。

$num = $stmt->rowCount(); 

しかし、オブジェクト以外のエラーでメンバー関数rowCount()への呼び出しを取得します。phpとWeb開発に非常に慣れていないため、混乱し、動作させる方法がわかりません。誰かが私を助けてくれますか?これがdb.phpファイルのコードです

<?php
require "config.php";


function DBconnect($config) {
    try {
        $conn = new PDO('mysql:host=localhost;dbname=' . $config['database'],
                        $config['username'],
                        $config['password']);

        $conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

        return $conn;
    } catch(Exception $e) {
        return false;
    }
}

function query($query, $bindings, $conn) {
    $stmt = $conn->prepare($query);
    $stmt->execute($bindings);

    return $stmt;
}

そして、これがログインページであるindex.phpファイルのコードです。

<?php

// Allow sessions to be passed so we can see if the user is logged in
session_start();

// include the necessary files
require "db.php";
require "functions.php";
include "index.view.php";


//conect to the database so we can check, edit or ,data to our users table
$conn = DBconnect($config);

// if the user has submitted the form
if( $_SERVER["REQUEST_METHOD"] === "POST") {

    //protect the posted value then store them to variables
    $username = protect($_POST["username"]);
    $password = protect($_POST["password"]);

    //Check if the username or password boxes were not filled in
    if ( !$username || !$password ){
        // if not display an error message.
        echo "You need to fill in a username and password!";
    }else
        // if correct continue cheking

        //select all the rows where the username and password match the ones submitted by the user
        query(  "SELECT * FROM users WHERE username = :username",
                array("username" => $username),
                $conn);
        $num = $stmt->fetchColumn(); 


        //check if there was not a match
        if( $num == 0) {
            //if not display an error message
            echo "The username you entered does not exist!";
        }else{
            //if there was a mactch continue chekcing

            //select all rows where the username and password match the ones submitted by the user
            query( "SELECT * FROM users WHERE username =:username && password = :pasword",
                    array("username" => $username, "password" => $password ),
                    $conn);
            $num = $stmt->fetchColumn();    

            //check if there was not a match
            if( $num == 0) {
                //if not display error message
                echo "Username and password do not mactch";
            }else {
                //if there was continue checking

                //split all the fields from the correct row into an associative array
                $row = $user->fetch(PDO::FETCH_ASSOC);
                //check to see if the user has not activated their account
                if($row["active"] != 1) {
                    //if not display an error message
                    echo "You have not yet activated your account!";
                }else {
                    //if so then log them in

                    // set the login session storing their id. We use this to
                    // see if they are logged in or not.
                    $_SESSION["uid"] = $row["id"];
                    //show message confirming that they are loggd in
                    echo "You have succesfully logged in!";
                    //update the online field to 50 seconds in the future
                    $time = date("u")+50;
                    query( "UPDATE users SET online = :time WHERE id = :id",
                            array("time" => $time, "id" => $_SESSION["uid"]),
                            $conn);
                    //redirect them to the usersonline page
                    header("Location: usersOnline.php");
                }
            }


    }
}           
4

3 に答える 3

2

$stmtの戻り値として取得するのを逃しましたquery()。呼び出しを次のように変更します。

$stmt = query(....);
$num = $stmt->rowCount(); 

詳細な通知を行うことは安全ではないと考えられることに注意してください。

  • ユーザー名が間違っていた
  • パスワードが間違っていた
  • どちらも間違っています。

これを行うと、攻撃者が有効なユーザー名を簡単に取得できます。ユーザー名があれば、有効なアカウントのパスワードを取得するのに必要な労力ははるかに少なくなります。

またrowCount()、すべてのデータベース ドライバーによって行数が返されるわけではないため、そのためには使用しません。そのため、別のデータベースを使用していると、コードが失敗する可能性があります。

クエリを次のように変更します。

SELECT count(*) AS number_of_rows, * FROM users WHERE username =:username && password = :pasword"

... 次に、結果セットから 'number_of_rows' をフェッチします。

if ( !$username || !$password ){
    // if not display an error message.
    echo "You need to fill in a username and password!";
}else

    //select the number of rows where the username and password match the ones submitted by the user
    query(  "SELECT count(*) as number_of_records, * FROM users WHERE username = :username AND password = :password",
            array("username" => $username, "password" => "$password"),
            $conn);
    $record = $stmt->fetch();
    if($record['number_of_records'] !== '1') {
        echo 'wrong username and / or password';
    }
}

さらに注意:暗号化されていないパスワードをデータベースに保存しないでください

代わりに、sha1 や md5 などのソルト付き一方向ハッシュ関数によってハッシュされたパスワードを保存する必要があります。簡潔にするために、ここでは例を挙げません。これをググるか、SOで別の質問をします。

于 2013-03-05T11:53:59.687 に答える
1

query()関数はステートメントを返しますが、呼び出し元からの戻り値を保存していません。

変化する

query(.....);

$stmt = query(.....);
于 2013-03-05T11:54:14.053 に答える
0

私はそのような肥大化したコードに耐えられません。したがって、これが適切なバージョンであり、すべての役に立たない不要で誤ったコードはありません。

if( $_SERVER["REQUEST_METHOD"] == "POST") {
    $sql = "SELECT id,active FROM users WHERE username=? && password=?";
    $stm = query($sql, array($_POST["username"], $_POST["password"]), $conn);
    $row = $stm->fetch(PDO::FETCH_ASSOC);
    if(!$row) {
        echo "Username and password do not mactch";
    } elseif($row["active"] != 1) {
        echo "You have not yet activated your account!";
    } else {
        $_SESSION["uid"] = $row["id"];
        $time = date("u")+50;
        $sql  = "UPDATE users SET online=? WHERE id=?";
        query($sql, array($time, $row["id"]), $conn);
        header("Location: usersOnline.php");
        exit;
    }
}           
于 2013-03-05T12:11:42.667 に答える