PHP新手求助:SHA512加密后登录验证失败问题
登录时SHA512加密密码验证失败的问题排查与解决
嘿,作为PHP新手能主动放弃不安全的MD5,选择SHA512加密密码,这点必须给你点个赞!不过遇到登录验证失败的问题别着急,咱们一步步来排查:
先把你贴的核心代码整理清楚:
登录核心代码
$username = mysqli_real_escape_string($con,$username); $password = stripslashes($_REQUEST['password']); $password = mysqli_real_escape_string($con,$password); $password = hash('sha512',$password); //Checking is user existing in the database or not $query = "SELECT * FROM `users` WHERE username='$username' AND password='".$password."'"; $result = mysqli_query($con,$query) or die(mysql_error()); $rows = mysqli_num_rows($result); $row = mysqli_fetch_array($result); if($rows==1){ // 登录成功逻辑 }
注册核心代码
//Strip & Escape PW $password = stripslashes($_REQUEST['password']); $password = mysqli_real_escape_string($con,$password); $sql_u = "SELECT username FROM users WHERE username='$username'"; $sql_e = "SELECT email FROM users WHERE email='$email'"; $res_u = mysqli_query($con, $sql_u); $res_e = mysqli_query($con, $sql_e); if (mysqli_num_rows($res_u) > 0) { $name_error = "Sorry... username already taken"; } else if(mysqli_num_rows($res_e) > 0){ $email_error = "Sorry... email already taken"; } else{ $query = "INSERT INTO users (username, email, password) VALUES ('$username', '$email', '".hash('sha512',$password)."')"; $results = mysqli_query($con, $query); echo 'You Have Registered Successfully!<br>'; }
最可能的问题:数据库字段长度不够
SHA512加密后的哈希值是128个十六进制字符,如果你的users表中password字段的长度设置得不够(比如设成了VARCHAR(64)或者更短),存储时就会自动截断哈希值,导致登录时生成的完整哈希和数据库里截断后的哈希不匹配——这是新手最容易踩的坑!
解决方法:把数据库中password字段的类型改成VARCHAR(128)或者TEXT,然后重新注册一个用户测试登录。
次要问题:密码处理逻辑的冗余与风险
你现在用stripslashes和mysqli_real_escape_string处理密码其实没必要,甚至可能出问题:
stripslashes是为了处理早年PHP开启magic_quotes_gpc时自动添加的反斜杠,但现在这个配置早就被废弃了,用它反而会意外修改密码(比如用户密码里真的有反斜杠,会被去掉)mysqli_real_escape_string是用来防止SQL注入的,但直接拼接SQL语句本身就不安全,应该用预处理语句替代
更推荐的安全方案:用PHP原生密码函数
其实SHA512也不是最安全的选择——它是快速哈希算法,容易被暴力破解。PHP自带的password_hash()和password_verify()才是最佳实践,它们会自动加盐,而且哈希算法会随着PHP版本更新自动升级,示例代码如下:
注册时的写法
// 直接获取原始密码,不需要额外转义 $password = $_REQUEST['password']; // 生成安全的哈希密码,PASSWORD_DEFAULT会自动使用当前最安全的算法(目前是bcrypt) $hashedPassword = password_hash($password, PASSWORD_DEFAULT); // 用预处理语句插入数据,彻底避免SQL注入 $stmt = mysqli_prepare($con, "INSERT INTO users (username, email, password) VALUES (?, ?, ?)"); mysqli_stmt_bind_param($stmt, "sss", $username, $email, $hashedPassword); mysqli_stmt_execute($stmt); echo 'You Have Registered Successfully!<br>';
登录时的写法
$username = $_REQUEST['username']; $password = $_REQUEST['password']; // 用预处理语句查询用户的哈希密码 $stmt = mysqli_prepare($con, "SELECT password FROM users WHERE username = ?"); mysqli_stmt_bind_param($stmt, "s", $username); mysqli_stmt_execute($stmt); mysqli_stmt_bind_result($stmt, $hashedPassword); mysqli_stmt_fetch($stmt); // 用password_verify验证密码,不需要手动哈希 if (password_verify($password, $hashedPassword)) { // 登录成功逻辑 echo "登录成功!"; } else { // 密码错误 echo "用户名或密码无效!"; }
注意:用password_hash()生成的哈希最长是255个字符,所以数据库password字段要设成VARCHAR(255)。
你可能遗漏的要点
你之前参考的文章里的验证逻辑是对的,但前提是数据库里存储的是完整的哈希值——你大概率是忽略了数据库字段长度的问题,导致哈希被截断,这才是验证失败的核心原因。
内容的提问来源于stack exchange,提问作者user9707828
相关产品推荐
相关产品推荐

