这是一个非常简短,简单明了的代码,我写的用于我的网站登录用户。我希望有人可以查看它并告诉我它是否有什么问题可以使用一些改进。
提前致谢!
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;
}
答案 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
我的方式:
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'];
}
但是,可以进行一些概念上的改进
将您的代码与此代码进行比较:
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'];
}