这是用户登录的好方法吗?

时间:2011-03-26 04:23:19

标签: php sql security login

这是一个非常简短,简单明了的代码,我写的用于我的网站登录用户。我希望有人可以查看它并告诉我它是否有什么问题可以使用一些改进。

提前致谢!

session_start();

/* connect to the db */
define("INCLUDED-PUBLIC", true);
include('dbConnection.php');   

/* define safe variables */
$login = mysqli_real_escape_string($connection, $_POST['login-email']);
$pass = md5($_POST['login-pass']);

/* send the query */
$query = mysqli_query($connection, "
  SELECT `user_id`
    FROM `users`
   WHERE `user_contact_email`='$login'
     AND `user_password`='$pass'
   LIMIT 1
");

/* does such account exist? */
$count = mysqli_num_rows($query);

if ($count > 0){

   /* user exists, loggin' in! */
   $data = mysqli_fetch_array($query);
   $userID = $data['user_id'];
   $_SESSION['user']['user_id'] = $userID;

}

4 个答案:

答案 0 :(得分:2)

实际上,还有很大的提升空间。

首先:您应该在散列算法中添加random salt以防止预先计算攻击。 (搜索rainbow table

第二:你应该从数据库中获取user_password值并在PHP端进行比较。

  

重要

     

调用PASSWORD()的语句可能会记录在服务器日志或历史文件中,例如〜/ .mysql_history,这意味着任何对该信息具有读访问权限的人都可以读取密码。请参见第5.3.2节“MySQL中的密码安全性”。

来源:http://dev.mysql.com/doc/refman/5.1/en/encryption-functions.html#function_password

第三:不要使用MD5这是一个很好的哈希算法,但出于安全考虑而被视为已损坏。如果您使用PHP 5.3或更高版本,请使用crypt和CRYPT_BLOWFISH PHP中的CRYPT_BLOWFISH是Bcrypt哈希的实现。 Bcrypt基于Blowfish分组密码,利用它昂贵的密钥设置来减慢算法速度。

另外:不要在查询中使用LIMIT,而是在user_contact_email上添加UNIQUE约束。使用LIMIT是一种技巧,可以掩盖重复的用户电子邮件,并在以某种方式输入重复的电子邮件时导致意外的结果。

最后:为什么不使用a standard library 安全性往往要复杂得多,并且具有比大多数程序员单独解决的更多隐形搞砸可能性,使用标准库几乎总是最简单的,并且大多数(如果不是唯一的)安全选项可用。 (另请阅读:Help me make my password storage safe

答案 1 :(得分:1)

我唯一想改变的是:

$pass = md5($_POST['login-pass']);

类似于:

$pass = hash('whirlpool', $_POST['login-pass']);

并且还会在注册时更改数据库中的存储方式。

除此之外,一切都很好。

答案 2 :(得分:1)

要改变的事情

  • include改为require_once
  • 检查密码和电子邮件是否为空
  • 您还检查有效的电子邮件但密码无效
  • 存储到会话后释放结果集
  • 关闭mysqli连接
  • 如果用户/电子邮件无效,则发送回

我的方式:

session_start();



require_once('dbConnection.php');
/* connect to the db */
define("INCLUDED-PUBLIC", true);


/* define safe variables */
if(!empty($_POST['login-pass']) && !empty($_POST['login-email']) )
{
    $login = mysqli_real_escape_string($connection, $_POST['login-email']);
    $pass = md5($_POST['login-pass']);

    /* send the query */
    $query = mysqli_query($connection, "
      SELECT `user_id`
        FROM `users`
       WHERE `user_contact_email`='$login'
            AND `user_password`='$pass'
        LIMIT 1
    ");

    /* does such account exist? */
    $count = mysqli_num_rows($query);

    if ($count > 0){
       /* user exists, loggin' in! */
       $data = mysqli_fetch_array($query);
       $_SESSION['user']['user_id'] = $data['user_id'];        
       /* free result set */
       mysqli_free_result($query);
       mysqli_close($connection);
    }
    else {
            header("location:login.php");
            exit();
    }

}

答案 3 :(得分:1)

一般来说,您的代码没问题,只能进行微小的改进。

  • 计算行是不必要的,获取数组将使用更短的代码执行相同的操作。
  • 需要一些错误处理。您必须检查查询结果并在失败时引发错误
  • 代码结构和可读性。
    编写可读代码可以省略明显的注释。 include('dbConnection.php');是不言自明的,不是吗? 代码中的$ query变量不包含查询,而是查询结果。因此,您正在混淆自己的代码,使其可读性降低。始终使用合理的名称,它将为您节省无用的评论。
像这样

define("INCLUDED-PUBLIC", true);
include('dbConnection.php');   
$login = mysqli_real_escape_string($connection, $_POST['login-email']);
$pass  = md5($_POST['login-pass']);

$query = "SELECT `user_id` FROM `users` WHERE `user_contact_email`='$login'
                                               AND `user_password`='$pass'";

$result = mysqli_query($connection, $query);
if (!$result) trigger_error(mysqli_error($connection).$query);

if ($data = mysqli_fetch_array($query)){
   session_start();
   $_SESSION['user']['user_id'] = $data['user_id'];
}

但是,可以进行一些概念上的改进

  • 始终首选使用占位符将数据插入查询中。
  • 密码腌制。这是一个漫长而模糊的故事,每个人都对它印象深刻,几乎没有人理解这件事。但它可以归结为简单的事情:
    具有特定于站点的盐,在您的dbconnect文件中定义,并使用它和用户的电子邮件添加密码。如果密码很弱,它将无济于事,但如果密码很强,将会有所帮助。
  • 有一些库来简化数据库调用是必须的:

将您的代码与此代码进行比较:

define("INCLUDED-PUBLIC", true);
include('dbConnection.php');   
$pass  = md5(SITE_SALT.$_POST['login-email'].$_POST['login-pass']);
$query = "SELECT `user_id` FROM `users` WHERE `user_contact_email`=? AND `user_password`=?";
$data  = dbgetone($query, $_POST['login-email'],$pass);
if ($data){
   session_start();
   $_SESSION['user']['user_id'] = $data['user_id'];
}