【发布时间】:2021-03-01 08:16:59
【问题描述】:
您好,我正在为我的项目开发一个忘记密码的 php 系统。 我想向我的用户发送一封电子邮件,以便他们可以单击链接重置密码。 但是当我打开收件箱时,我得到的是 html 文本而不是链接。 我尝试了其他方法,例如在消息中添加标头,但它仍然是 html 代码。 这是我的代码:
<?php
$errors = [];
$user_id = "";
$db = mysqli_connect('localhost', 'root', 'mySQLpassword', 'registration');
if (isset($_POST['login_user'])) {
$user_id = mysqli_real_escape_string($db, $_POST['user_id']);
$password = mysqli_real_escape_string($db, $_POST['password']);
if (empty($user_id)) array_push($errors, "Username or Email is required");
if (empty($password)) array_push($errors, "Password is required");
if (count($errors) == 0) {
$password = md5($password);
$sql = "SELECT * FROM users WHERE username='$user_id' OR email='$user_id' AND password='$password'";
$results = mysqli_query($db, $sql);
if (mysqli_num_rows($results) == 1) {
$_SESSION['username'] = $user_id;
$_SESSION['success'] = "You are now logged in";
header('location: index.php');
}else {
array_push($errors, "Wrong credentials");
}
}
}
if (isset($_POST['reset-password'])) {
$email = mysqli_real_escape_string($db, $_POST['email']);
query = "SELECT email FROM users WHERE email='$email'";
$results = mysqli_query($db, $query);
if (empty($email)) {
array_push($errors, "Your email is required");
}else if(mysqli_num_rows($results) <= 0) {
array_push($errors, "Sorry, no user exists on our system with that email");
}
$token = bin2hex(random_bytes(50));
if (count($errors) == 0) {
$sql = "INSERT INTO password_reset(email, token) VALUES ('$email', '$token')";
$results = mysqli_query($db, $sql);
$to = $email;
$subject = "Reset your password";
$msg = "Hi there, click on this <a href=\"new_password.php?token=" . $token . "\">link</a> to reset your password on our site";
$msg = wordwrap($msg,70);
$headers = "From: info@gmail.com";
mail($to, $subject, $msg, $headers);
header('location: pending.php?email=' . $email);
}
}
if (isset($_POST['new_password'])) {
$new_pass = mysqli_real_escape_string($db, $_POST['new_pass']);
$new_pass_c = mysqli_real_escape_string($db, $_POST['new_pass_c']);
$token = $_SESSION['token'];
if (empty($new_pass) || empty($new_pass_c)) array_push($errors, "Password is required");
if ($new_pass !== $new_pass_c) array_push($errors, "Password do not match");
if (count($errors) == 0) {
$sql = "SELECT email FROM password_reset WHERE token='$token' LIMIT 1";
$results = mysqli_query($db, $sql);
$email = mysqli_fetch_assoc($results)['email'];
if ($email) {
$new_pass = md5($new_pass);
$sql = "UPDATE users SET password='$new_pass' WHERE email='$email'";
$results = mysqli_query($db, $sql);
header('location: index.php');
}
}
}
?>
任何帮助都将被排除在外!
【问题讨论】:
-
这是学术代码还是用于生产网站?
-
警告:当使用
mysqli时,您应该使用parameterized queries 和bind_param将用户数据添加到您的查询中。 请勿使用手动转义和字符串插值或连接来完成此操作,因为您总是会创建严重的SQL injection bugs。意外未转义的数据是一个严重的风险。使用绑定参数不那么冗长,并且更容易检查以检查您是否正确执行。 -
注意:object-oriented interface to
mysqli明显不那么冗长,使代码更易于阅读和审核,并且不容易与过时的mysql_query接口混淆,因为缺少单个i会导致麻烦。示例:$db = new mysqli(…)和$db->prepare("…")过程接口是 PHP 4 时代的产物,不应在新代码中使用。此外,程序界面的错误检查和报告不那么严格,使调试工作受挫。 -
托比,欢迎来到 StackOverflow。除了@tadman 关于查询的完全正确的 cmets 之外,您的代码还在您的密码上使用 md5 哈希(未加盐)。很长一段时间以来,md5 一直不被认为是安全的密码存储——而且可以说永远不应该如此。有许多更好且易于使用的替代品。请帮您的用户一个忙,在您解决数据库反馈并替换密码处理之前不要部署此代码。
-
警告:编写访问控制层并不容易,而且有很多机会严重错误。任何现代的development framework,比如Laravel,都带有一个内置的authentication system,还有authentication libraries可以使用。至少遵循recommended security best practices 并且永远不要将密码存储为纯文本 或像 SHA1 或 MD5 这样的弱散列。