PHP注册脚本

时间:2013-02-13 17:38:07

标签: php refactoring registration

所以我正在尝试为我的网站编写这个脚本。 它看起来很混乱和破碎。 也许有人可以帮我整理一下并解释可能不正确的内容。 还有,有办法缩短它,看起来有点不安全。 谢谢。

<?php

class Register
{
    private $username;
    private $password;
    private $password2;
    private $passmd5;
    private $email;
    private $email2;

    private $errors;
    private $rtoken;

    public function __construct()
    {
        $this->errors = array();

        $this->username  = $this->filter($_POST['ruser']);
        $this->password  = $this->filter($_POST['rpass']);
        $this->password2 = $this->filter($_POST['rpass2']);
        $this->email     = $this->filter($_POST['remail']);
        $this->email2    = $this->filter($_POST['remail2']);
        $this->rtoken    = $_POST['rtoken'];

        $this->passmd5 = md5($this->password);
    }

    public function process()
    {
        if ($this->valid_rtoken() && $this->valid_data())
            $this->register();

        return count($this->errors) ? 0 : 1;
    }

    public function filter($var)
    {
        return preg_replace('/[^a-zA-Z0-9@.]/', '', $var);
    }
    public function register()
    {
        mysql_query("INSERT INTO users(username,password,email) VALUES ('{$this->username}','{$this->passmd5}','{$this->email}')");

        if (mysql_affected_rows() < 1)
            $this->errors[] = '<font color="red">Database error</font>';
    }

    public function user_exists()
    {
        $data = mysql_query("SELECT ID FROM users WHERE username = '{$this->username}'");

        return mysql_num_rows($data) ? 1 : 0;
    }

    public function email_exists()
    {
        $data = mysql_query("SELECT ID FROM users WHERE email = '{$this->email}'");

        return mysql_num_rows($data) ? 1 : 0;
    }

    public function show_errors()
    {
        echo "";

        foreach ($this->errors as $key => $value)
            echo $value . "<br>";
    }

    public function valid_data()
    {
        if ($this->user_exists())
            $this->errors[] = '<font color="red">Username Exists</font>';
        if ($this->email_exists())
            $this->errors[] = '<font color="red">email exists</font>';
        if (empty($this->username))
            $this->errors[] = '<font color="red">check your username</font>';
        if (empty($this->password))
            $this->errors[] = '<font color="red">check your password</font>';
        if ($this->password != $this->password2)
            $this->errors[] = '<font color="red">Passwords do not match</font>';
        if (empty($this->email) || !eregi('^[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z]{2,4}$', $this->email))
            $this->errors[] = '<font color="red">Check your email</font>';
        if ($this->email != $this->email2)
            $this->errors[] = '<font color="red">Emails do not match</font>';

        return count($this->errors) ? 0 : 1;
    }


    public function valid_rtoken()
    {
        if (!isset($_SESSION['rtoken']) || $this->rtoken != $_SESSION['rtoken'])
            $this->errors[] = '<font color="red">Check</font>';

        return count($this->errors) ? 0 : 1;
    }
}

?>

1 个答案:

答案 0 :(得分:3)

Swoosh,总有更好的方法来编写代码。我希望挑战你重新思考为什么你的代码很长,为什么它可能不安全,而不是为你重写你的代码。希望你能以这种方式学到更多东西。

首先,使用MD5散列密码是完全不安全的。请忘记MD5曾经存在过,请不要使用SHA1来保证安全。相反,你应该使用bcrypt或PBKDF2(使用SHA2或Whirlpool和~2000 +轮次)。我建议您参考我对Secure Hash and Salt for PHP Passwords的回答,获取有关文章和库的提示和链接,以帮助实现更好的安全性。

其次,自PHP 5.5起,mysql_ *函数为deprecated。使用MySQLi可以帮助您,但您应该使用一致的界面(如PDO)来处理连接,并查询转义/过滤。虽然您可能没有在PHP 5.5中构建软件,但是如果主机决定升级您的PHP版本,您将无法控制。尽可能地优化未来的兼容性。此外,PDO还有一些很好的功能,在its documentation中有解释。

第三,不应使用正则表达式来“过滤”查询变量。您可以做的最安全的事情是对任何数字使用intval / floatval,并通过您使用的数据库库转义其余数据,例如mysql_escape_string(或mysqli_real_escape_string)或使用prepared statements(这将是为你清理变量。)

第四,您将显示逻辑放入对象中。想一想:这个对象实现的目的/角色是什么?它是否处理注册逻辑?它是否存储注册数据?在这里使用Single Responsibility Principle是个好主意。看起来该对象应该像混合模型控制器一样,其中包含表示信息。您可以将其扩展为RegistrationModel和RegistrationController类,以处理临时存储数据,甚至决定执行其他操作。但请记住,你的班级承担的责任越多,它就越有必要打破。

此外,通过将Register的所有属性设为私有,您不能有多种注册方式。如果您想要简化流程,例如通过OAuth(例如Twitter或Facebook)登录,但需要重用Register中的某些逻辑,该怎么办?这些属性至少应该受到保护,以便您可以继承这些属性,甚至是公共属性,以便另一个对象可以与它们交互(例如,通知用户注册成功的对象)。