我为android制作了一个完整的工作注册/登录系统,一切都是通过空中传送和服务器端数据库进行的,问题是现在我的密码被直接保存到数据库中(没有加密),我搜索了大量的网站和SoF帖子和线程,但没有任何实际帮助。
我读过关于md5和sha1、blowfish和bcrypt的文章,但无法理解这种加密术的正确实现。。
连接是使用php请求进行的。寄存器代码如下:
if($_SERVER['REQUEST_METHOD']=='POST'){
$username = $_POST['username'];
$password = $_POST['password'];
$email = $_POST['email'];
$Firstname = $_POST['fname'];
$Lastname = $_POST['lname'];
$Date = $_POST['Date'];
require_once('db_config.php');
$check_username_email = "SELECT * FROM Users WHERE Username ='$username' AND Email = '$email'";
$check_u_e = mysqli_fetch_array(mysqli_query($db,$check_username_email));
$check_username = "SELECT * FROM Users WHERE Username ='$username'";
$check_u = mysqli_fetch_array(mysqli_query($db,$check_username));
$check_email = "SELECT * FROM Users WHERE Email ='$email'";
$check_e = mysqli_fetch_array(mysqli_query($db,$check_email));
if(isset($check_u_e)){
echo 'Username AND Email already exist, please change them Both.';
}
else if(isset($check_u)){
echo 'Username already exists, please change it.';
}
else if (isset($check_e)){
echo 'Email already exists, please change it.';
} else{
$sql = "INSERT INTO Users(Email,Username,Bio,Password,Fname,Lname,Regiser_Date) VALUES ('$email','$username',NULL,'$password','$Firstname','$Lastname','$Date')";
if(mysqli_query($db,$sql)){
echo "You have been successfully Registered";
} else{
echo "Sorry, something went wrong - Try again.";
}
}
}else{
echo 'Server error - Please try again later.';
mysqli_close($db);
}
我的登录名在这里:
if($_SERVER['REQUEST_METHOD']=='POST'){
$username = $_POST['username'];
$password = $_POST['password'];
require_once('db_config.php');
$sql = "SELECT * FROM Users WHERE Username = '$username' AND Password = '$password'";
$result = mysqli_query($db,$sql);
$check = mysqli_fetch_array($result);
if(isset($check)){
echo 'Logged In';
}
else{
echo 'Failed to login';
}
}
除了加密,一切都很好。有人能帮我渡过难关吗?我读到它需要两个方面,一个来自客户端(android应用程序),另一个来自php服务器端
要加密密码,可以使用password_hash函数。在您的注册代码中,在插入查询之前添加以下内容:
$options = [
'cost' => 12,
];
$password = password_hash($password, PASSWORD_BCRYPT, $options);
这将在注册时使用BCRYPT算法加密通过POST阵列接收的密码。BCRYPT算法生成60个字符的散列(将输入字符串剪切为70个字符),因此,在您的数据库中,您需要有一个CHAR(60)密码字段来存储散列后的密码。
不过,您也可以在$options中添加自己的salt,正如php文档中所写的那样
强烈建议您不要为此函数生成自己的盐。如果您没有指定安全盐,它将自动为您创建一个安全盐。如上所述,在PHP7.0中提供salt选项将生成一个弃用警告。在未来的PHP版本中,可能会删除对手动提供salt的支持。
既然你在数据库中已经有了加密密码,那么在登录脚本中,你需要从数据库中检索散列密码,然后用password_verify()函数将其与输入的密码进行比较:
$sql = "SELECT password FROM Users WHERE Username = '$username'";
$result = mysqli_query($db,$sql);
if(!$row = mysqli_fetch_assoc($result)){
echo "failed to login(invalid username)";
die();
//login failed->add code to redirect to login page
}
if(password_verify($password, $row['password'])){
//password match the stored hash
echo "logged in";
//sucessfully logged->retrive all additional data you need, save session, redirect to homepage etc...
}
else echo "failed to log in(invalid password)";
您可以在这里找到关于password_hash()和password_verify()的所有信息,但请考虑:
- 密码在通过POST阵列发送到服务器时,在登录和注册时仍然容易受到攻击。出于这个原因,您应该安装一个证书,以便使用HTTPS协议对从服务器流到客户端的数据进行加密,反之亦然(在这里查看apache下的配置ssl)
- 你没有对输入采取任何预防措施,所以你的代码很容易被注入。当您有未经测试的数据时,我建议使用mysqli或PDO准备的语句来查询数据库
所以在数据库中存储密码时,会是这样的,使用任何哈希或加密,如bcrypt、md5、sha1,并将其存储在数据库中。当用户想要登录时,再次使用相同的哈希或加密机制将存储在DB中的值和用户传递的值进行比较。如果是,则成功登录。
所以现在,
你对插入的查询会得到这样的结果,
$sql = "INSERT INTO Users(Email,Username,Bio,Password,Fname,Lname,Regiser_Date) VALUES ('$email','$username',NULL,'md5($password)','$Firstname','$Lastname','$Date')";
和
$sql = "SELECT * FROM Users WHERE Username = '$username' AND Password = 'md5($password)'";
然后使用Bcrypt、
中显示了一个示例
$options = [
'cost' => 12,
];
echo password_hash("password", PASSWORD_BCRYPT, $options)."'n";
http://php.net/manual/en/function.password-hash.php