PDO-致命错误:在非对象上调用成员函数fetch() [英] PDO - Fatal error: Call to a member function fetch() on a non-object

查看:133
本文介绍了PDO-致命错误:在非对象上调用成员函数fetch()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我尝试运行以下PHP代码,则会得到

if I try to run the following PHP code, I get a

在非对象上调用成员函数fetch().

Call to a member function fetch() on a non-object.

你知道为什么吗?我在另一个网站上使用了相同的代码,效果很好.

Do you know why? I use the same code on another site, where it works just fine.

<?php
$username = ($_GET ['user']);
try {
    $dbh = new PDO("mysql:host=localhost;dbname=***", '***', '***');    
} catch (PDOException $e) {
    echo $e->getMessage();
}
$sth = $dbh->query( "SELECT user, captcha 
    FROM xf_captcha WHERE user='$username'" );
print_r($sth->fetch());
?>



$sth = $dbh->query( "SELECT username, user_state, last_activity, alerts_unread, conversations_unread, message_count 
    FROM xf_user WHERE username='$user'" );
$row = $sth->fetch();


Edit2:


这看起来安全吗,我应该做更多的事情吗?

Does this look safe, should I do more ?

<?php
$username = ($_GET ['user']);
try {
    $dbh = new PDO("mysql:host=localhost;dbname=***", '***', '***');
} catch (PDOException $e) {
    echo $e->getMessage();
}
$sth = $dbh->prepare("SELECT username, captcha, timestamp 
    FROM xf_captcha 
    WHERE username = :username", array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->execute(array(':username' => $username));
print_r($sth->fetch());
?>

推荐答案

您的代码在问题的顶部具有变量$username,但是在底部具有$user.

Your code has the variable $username in the top part of your question, but you then have $user in the bottom section.

您可能是想使用相同的变量吗?

Are you perhaps meaning to use the same variable?

$username = ($_GET ['user']);
$sth = $dbh->query( "SELECT username, user_state, last_activity, alerts_unread, conversations_unread, message_count 
  FROM xf_user WHERE username='$user'" );
  //                           ^^ Should this ALSO be $username ?   
$row = $sth->fetch();

好的,现在您只是对您的PDO::ATTR_EMULATE_PREPARES可爱.观察一下:

Okay, now you are just being cute with your PDO::ATTR_EMULATE_PREPARES. Observe this:

数据库和表结构:

Database changed
mysql> show tables
    -> ;
+----------------+
| Tables_in_prep |
+----------------+
| users          |
+----------------+
1 row in set (0.00 sec)

mysql> select * from users;
+----+---------+--------+
| id | userid  | pass   |
+----+---------+--------+
|  1 | Fluffeh | mypass |
+----+---------+--------+
1 row in set (0.00 sec)

以及从您的站点复制的一些PHP代码,并添加了PDO属性:

And some PHP code that is copied from yours, with the added PDO attribute:

<?php
    //$username = ($_GET ['user']);
    $username="Fluffeh";

    $dbh = new PDO('mysql:host=localhost;dbname=prep', 'prepared', 'example');
    $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);

    $sth = $dbh->query( "SELECT userid, pass FROM users WHERE userid='$username'" );
    echo "Trying to use $username.\n";
    print_r($sth->fetch());
    echo "----------------------------------------\n\n";
?>

<?php
    //$username = ($_GET ['user']);
    $username="user2693017";

    $dbh = new PDO('mysql:host=localhost;dbname=prep', 'prepared', 'example');
    $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);

    $sth = $dbh->query( "SELECT userid, pass FROM users WHERE userid='$username'" );
    echo "Trying to use $username.\n";
    print_r($sth->fetch());
    echo "----------------------------------------\n\n";
?>

<?php
    //$username = ($_GET ['user']);
    $username="Oh my' or 1=1 or 'm=m";

    $dbh = new PDO('mysql:host=localhost;dbname=prep', 'prepared', 'example');
    $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);

    $sth = $dbh->query( "SELECT userid, pass FROM users WHERE userid='$username'" );
    echo "Trying to use $username.\n";
    print_r($sth->fetch());
    echo "----------------------------------------\n\n";
?>

<?php
    //$username = ($_GET ['user']);
    $username="(select id from users limit 1)";

    $dbh = new PDO('mysql:host=localhost;dbname=prep', 'prepared', 'example');
    $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);

    $sth = $dbh->query( "SELECT userid, pass FROM users WHERE id='$username'" );
    echo "Trying to use $username.\n";
    print_r($sth->fetch());
    echo "----------------------------------------\n\n";
?>

<?php
    //$username = ($_GET ['user']);
    // Changed this one to be a non-string, you might be checking an ID instead.
    $username="(select id from users limit 1)";

    $dbh = new PDO('mysql:host=localhost;dbname=prep', 'prepared', 'example');
    $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);

    $sth = $dbh->query( "SELECT userid, pass FROM users WHERE id=$username" );
    echo "Trying to use $username.\n";
    print_r($sth->fetch());
    echo "----------------------------------------\n\n";
?>

<?php
    //$username = ($_GET ['user']);
    $username="bob'; drop table users; \  
    ";
    // This one is tricker to do in PHP code. I could easily enter this into a text field however.

    $dbh = new PDO('mysql:host=localhost;dbname=prep', 'prepared', 'example');
    $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);

    //$sth = $dbh->query( "SELECT userid, pass FROM users WHERE id='$username'" );
    echo "Trying to use $username.\n";
    print_r($sth->fetch());
    echo "----------------------------------------\n\n";
?>

输出:

    Trying to use Fluffeh.
stdClass Object
(
    [userid] => Fluffeh
    [pass] => mypass
)
----------------------------------------


    Trying to use user2693017.
----------------------------------------


    Trying to use Oh my' or 1=1 or 'm=m.
stdClass Object
(
    [userid] => Fluffeh
    [pass] => mypass
)
----------------------------------------


    Trying to use (select id from users limit 1).
----------------------------------------


    Trying to use (select id from users limit 1).
stdClass Object
(
    [userid] => Fluffeh
    [pass] => mypass
)
----------------------------------------


    Trying to use bob'; drop table users; \  
        .
----------------------------------------

哦,我把最后一个保留到LAST的原因是现在数据库中的输出:

Oh, the reason I left the last one till LAST is this output now in my database:

mysql> show tables;
Empty set (0.00 sec)

是的,没错,我刚刚放了一张桌子.让我再说一遍,我有一条select语句,并且有一点点欺骗,我输入了一个值,任何人只要动脑筋并且有恶意,就可以在文本字段中输入该值,并删除您的表.

Yes, that's right, I just dropped a table. Let me say that again, I had a select statement, and with a little trickery I entered in a value that ANYONE with half a brain and some malicious intent could do into a text field, and DROPPED YOUR TABLE.

现在,如果您正确设置了东西,则可以为select语句设置一个不同的用户,并只授予他们数据库中的select权限,以阻止此类事情的发生-但是,让说实话...你不是吗?

Now, granted, if you are setting things up properly, you might well set up a different user for the select statements, and only grant them select rights from your database, to stop this sort of thing happening - but lets be honest... you aren't are you?

清楚地设置仿真是不够的.认真地说,现在请务必阅读该答案,如果您想确保自己的代码安全,请使用准备好的语句并使用参数.

Clearly setting that emulation is not enough. Seriously, now PLEASE do go read that answer, use prepared statements and use params if you want to be secure in your code.

这篇关于PDO-致命错误:在非对象上调用成员函数fetch()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆