好的,所以我正在编写我的网站的更改密码部分。
请注意,我只用PHP几周了。
这就是我之前使用md5进行密码加密的原因,但我研究了密码安全性,并决定使用PHP的crypt()函数来哈希我的密码,而不仅仅是md5左右。
我遇到了以前更改密码功能的问题,其中在将新密码保存到数据库中导致用户被注销后,usersession被中止。旧密码更改网站供参考:http://pastebin.com/hf6WhtEQ
我最初的做法是使用session_regenerate_id()
来更新会话,因为似乎只是更新cookie中的密码并不起作用。
这种方法似乎最初起作用,但经过进一步的测试,很明显它没用了。
所以我从头开始,创建了以下代码。
我还没有实现cookie,因为我仍然不确定如何去做,并且在我设置新cookie之前要确保我拥有强大的密码安全性。
现在我的计划如下:
我检查用户是否已登录以及该帐户的所有者。
我想检查数据库中的密码是否与$oldpass
中的密码匹配。
我想比较$newpass
和$repeatpass
,如果两个密码匹配,那么我想使用$newpass
隐藏crypt()
。
最后,我想使用新的加密密码更新数据库,并使用新的密码更新cookie,同时确保用户保持登录状态。
现在,我的问题是:
为什么我一直收到消息"该用户不存在或尚未激活,请按"即使标题明显包含用户名。
如何按照我的计划将一切都按照良好的方式进行处理。 (现在它是无序的,我不知道if语句的正确顺序应该是什么)。
change_pass.php:
<?php
include 'check_login_status.php';
$u="";
$oldpass=md5("");
//stripping both strings of white spaces
$newpass = preg_replace('#[^a-z0-9]#i', '', $_POST['newpass']);
$repeatpass = preg_replace('#[^a-z0-9]#i', '', $_POST['repeatpass']);
//get the username from the header
if(isset($_GET["u"])){
$u = preg_replace('#[^a-z0-9]#i', '', $_GET['u']);
} else {
header("location: compare_pass.php?u=".$_SESSION["username"]);
exit();
}
// Select the member from the users table
$sql = "SELECT * FROM users WHERE username='$u' AND password='$oldpass' LIMIT 1";
$user_query = mysqli_query($db_conx, $sql);
// Now make sure that user exists in the table
$numrows = mysqli_num_rows($user_query);
if($numrows < 1){
echo "That user does not exist or is not yet activated, press back";
exit();
}
$isOwner = "no";
//check if user is logged in owner of account
if($u == $log_username && $user_ok == true){
$isOwner = "yes";
}
$passhash = "";
if (($newpass) === ($repeatpass)) {
$passhash = crypt_sha256("$newpass", "B-Pz=0%5mI~SAOcW0pMUdgKQh1_B7H6sbKAl+9~O98E9MBPrpGOtE65ro~8R");
} else {
echo "comparison failed! :(";
}
//
if (isset($_POST["submit"]) &&($isOwner == "yes") &&($user_ok == true) &&($newpass) === ($repeatpass)) {
$sql = "UPDATE users SET `password`='$passhash' WHERE username='$u' LIMIT 1";
}
?>
<h3>Create new password</h3>
<form action="" method="post">
<div>Current Password</div>
<input type="text" class="form-control" id="password" name="oldpass" >
<div>New Password</div>
<input type="text" class="form-control" id="password" name="newpass" >
<div>Repeat Password</div>
<input type="text" class="form-control" id="password" name="repeatpass" >
<br /><br />
<input type="submit" name="submit" value="Submit">
<p id="status" ></p>
</form>
check_login_status.php:
<?php
session_start();
include_once("db_conx.php");
// Files that inculde this file at the very top would NOT require
// connection to database or session_start(), be careful.
// Initialize some vars
$user_ok = false;
$log_id = "";
$log_username = "";
$log_password = "";
// User Verify function
function evalLoggedUser($conx,$id,$u,$p){
$sql = "SELECT ip FROM users WHERE id='$id' AND username='$u' AND password='$p' AND activated='1' LIMIT 1";
$query = mysqli_query($conx, $sql);
$numrows = mysqli_num_rows($query);
if($numrows > 0){
return true;
}
}
if(isset($_SESSION["userid"]) && isset($_SESSION["username"]) && isset($_SESSION["password"])) {
$log_id = preg_replace('#[^0-9]#', '', $_SESSION['userid']);
$log_username = preg_replace('#[^a-z0-9]#i', '', $_SESSION['username']);
$log_password = preg_replace('#[^a-z0-9]#i', '', $_SESSION['password']);
// Verify the user
$user_ok = evalLoggedUser($db_conx,$log_id,$log_username,$log_password);
} else if(isset($_COOKIE["id"]) && isset($_COOKIE["user"]) && isset($_COOKIE["pass"])){
$_SESSION['userid'] = preg_replace('#[^0-9]#', '', $_COOKIE['id']);
$_SESSION['username'] = preg_replace('#[^a-z0-9]#i', '', $_COOKIE['user']);
$_SESSION['password'] = preg_replace('#[^a-z0-9]#i', '', $_COOKIE['pass']);
$log_id = $_SESSION['userid'];
$log_username = $_SESSION['username'];
$log_password = $_SESSION['password'];
// Verify the user
$user_ok = evalLoggedUser($db_conx,$log_id,$log_username,$log_password);
if($user_ok == true){
// Update their lastlogin datetime field
$sql = "UPDATE users SET lastlogin=now() WHERE id='$log_id' LIMIT 1";
$query = mysqli_query($db_conx, $sql);
}
}
?>
答案 0 :(得分:0)
他们登录时有旧的通行证,因为他们需要在登录时以明文形式提供给您。如果是这种情况,为什么不将两个密码从数据库中删除(旧的和新的)。如果它是旧的传递,md5它,如果它等于将新的加密密码(基于他们输入的内容)存储到数据库中(同时清除旧传递),如果它是新的传递,则通过新的比较隐藏方法。
另外,在旁注中,因为我们谈论的是安全问题。 Bind your parameters而不是像你那样把它们放在你的代码中!这实际上消除了sql注入的可能性,并允许您不必对所有输入运行正则表达式。
答案 1 :(得分:0)
我的方法出现了几件事。 首先,您提到使用crypt加密密码。这是数据散列的一种方式,而不是真正的加密。在php和mysql中,内置了正确加密的功能 - 这意味着密码可以在必要时解密,但可以安全存储。哈希例程(例如MD5)不安全且已被破坏,因此更强大的方法是使用256cipher和非常复杂的密钥加密密码。
例如,在mysql中:
aes_encrypt('password','complex key') /*to encrypt*/
aes_decrypt( '<encrypted pwd>,'complex key' ) /*to decrypt*/
第二:为了同意上面的Danbopes,bindParams几乎消除了sql注入攻击,这必须是一件好事。
Thridly:你提到将密码存储在cookie中 - 即使是以散列形式存储。这是一个非常糟糕的主意,是值得避免的。如果攻击者截获该cookie会怎么样?
最后 - mysqli很好,但在我看来,PDO是一个更好的选择 - 但这可能只是个人选择。