PDO登录脚本始终重定向到页眉页面

时间:2014-04-20 05:50:30

标签: php pdo

<?php
    include "config.php";
    class Users extends Config {
        public function login($username, $password) {
            try {
                $this->db->beginTransaction();
                $stmt = $this->db->prepare("SELECT `username`, `password` FROM `users` WHERE `username` = ? AND `password` = ? LIMIT 1");
                $stmt->execute(array($username, $password));
                if($stmt->rowCount == 1) {
                    while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
                        header("Location: index.php?p=loggedin");
                        exit();
                    }
                } else {
                    header("Location: index.php?p=false");
                    exit();
                }
                $this->db->commit();
            } catch(PDOException $ex) {
                $this->db->rollBack();

                echo $ex->getMessage();
            }
        }
    }
    $users = new Users();
?>

如上所示,我的代码有两个header()方法,其中一个重定向到登录页面,而另一个重定向到错误页面。
我相信据我所知,我的脚本应该按照我的输入重新指向登录页面,这是正确的,但它的行为方式是出乎意料的。
它重定向到错误页面而不是登录页面。请看一看,告诉我它不起作用的原因?谢谢!此外,如果您发现我的代码中存在任何缺陷,请随意提出一些批评,因为我希望改善自己。非常感谢。

1 个答案:

答案 0 :(得分:47)

  

我要发布一些有希望比上面那些帖子更有用的东西。这里有几种最佳实践可以让您在编码时更轻松;当然,当你把头包裹起来之后。

首先,这看起来像是您尝试应用程序的身份验证部分。如果用户传递了正确的用户名和密码,则需要显示正确的页面。我不知道你的申请范围,所以我不打算提出大的改变。

自动加载

您好像手动包含文件。 PHP有spl_autoload_register,如果你关注PSR-0(你真的应该看一下),这意味着你可以将你的目录结构映射到你的类1:1并且有类<当您要求时,em>自动为您解决。因此,当您说new Object,甚至(在您的情况下)extends Config时,如果您的Config班级位于您的最高级别,则会自动找到并使用它。这将让您了解namespaces

一旦您了解了命名空间的工作原理以及自动加载如何为您节省development time(我的意思是长期的重要时间),您就可以转到依赖管理工具,如{{3} }。 Composer基本上是您运行的脚本,可以为您生成自动加载器,然后您在应用程序开始时需要做的就是require_once __DIR__ . "/vendor/autoload.php"。但是说真的,看一些composer - 一旦你使用它们,你将永远不会回去,并且基本上会在你将来写的每一个应用程序中使用它们。

您也永远不需要多次输入include - 如果您尝试包含的文件,只会抛出警告还没有找到。看起来这个文件需要配置文件,所以在这种情况下你应该使用require_once - 这意味着你的代码将致命如果这个文件不是&#39;找到了(这似乎是你想要的)。

OOP

class Users extends Config出了什么问题。至少做得好,至少有一个好的命名约定(类名称的上限)。基本上,extends表示是-a 关系。您仅扩展以获得额外的功能 - 这是代码味道。您在此处说UserConfig。情况并非如此,如果您将来将此代码交给任何其他开发人员 - 他们就像&#34; WAIT,WTF&#34;。希望以更好的方式。

您的目标是:在类中拥有配置变量。所以,将它们传递给班级。我无法告诉您Config课程中的内容,但您应该查看autoloading tutorials;这是Dependency Injection pattern。基本上,您可以通过DI(通过构造函数)传递Config对象,然后解耦您的代码,以便您可以单独测试每个对象的优点,反而嘲笑其他对象。可测试的代码。依赖注入。谷歌吧。

因此,延长Config。改为通过您的配置:

class Users
{
    /**
     * @var Config
     */
    protected $config;

    /**
     * @constructor
     *
     * @param Config $config The class configuration, duh
     */
    public function __construct(Config $config)
    {
        $this->config = $config;
    }

    /** Snip **/
}

另请查看tutorial以帮助您编写其他开发人员可以轻松理解和解析的注释代码。

交易

您还使用了您真正不需要用于SELECT的交易。为什么不?由于交易允许您commitrollback - 但是当您进行选择时,您不会更改任何数据。因此,执行交易毫无意义。请删除它们,然后尝试通过SELECT检索数据。

您的标头代码

每个类,每个对象,应该有一个改变的理由。它所做的一项任务就是它。如果您有一些从数据库中读取的代码,比较一些字符串并保存到文件,那么您至少应该有3个类:一个从持久性中读取,一个执行比较,另一个保存到文件。这被称为phpdoc syntax,你可以阅读和谷歌。

考虑到这一点,这个单独的班级不应该负责发送标题。返回truefalse并让使用此类的类来代替。 这个类的责任 - 这应该只处理身份验证。

如果您选择了框架,则可以在ControllerView中执行此操作,具体取决于您与Single Responsibility Principle模式的接近程度 - 这实际上是不可能的它对Web应用程序的最严格意义(我把它放在那里为肛门人员提供)但实际上 - 你应该将你的顾虑分开,至少在你的代码库中遵守SRP。

安全

我绝不是安全专家,但您 所做的就是将您的用户名和密码传递给数据库。如果您正在哈希密码,那么您只需通过用户名从数据库中检索User然后计算密码是否与PHP代码中的哈希值匹配。这样您就不会将密码发送到数据库,这有助于(尽管只是一点点)对抗MVC。 PHP 5.5包含一些非常有用的SQL Injection函数来帮助您,但由于您可能不使用PHP 5.5,请查看password_*库。

什么是SQL注入?来自password_compat的更多信息,以及下面真正有用的图片。

SQL Injection Car

结论

这些只是一些指示,让您朝着更好的代码方向前进,您可以将其传递给其他能够理解它的开发人员,您可以为此感到自豪。看看像Bobby Tables这样的框架,这样您就不必担心身份验证,自动加载以及类似的事情 - 它们都是为您完成的。作曲家绝对是必须的。您需要逐个var_dump()开始逐行调试代码,直到您看到不符合预期的内容为止。调试101,它将帮助您,并帮助我们为您提供更多帮助。