You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

登录页错误提示异常及邮箱验证码登录改造技术求助

登录功能问题修复与邮箱验证码改造方案

一、修复登录失败提示问题

原代码的核心问题是:当用户名不存在时,查询结果为空,while循环不会执行,导致无法触发登录失败弹窗。以下是修复后的完整代码及说明:

修复后的PHP代码(含后续验证码功能)

<!DOCTYPE html>
<html lang="en">
<body>
<?php 
session_start(); // 开启session用于存储验证码
$servername = "localhost";
$username = "root";
$password = "";
$database = "my_db";

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$conn = mysqli_connect($servername, $username, $password, $database);
mysqli_set_charset($conn, 'utf8mb4');

// 处理登录请求
if(isset($_POST['login_Btn'])){
    $username = $_POST['username'];
    $password = $_POST['password'];
    $captcha = $_POST['captcha'];

    // 先验证验证码
    if(empty($_SESSION['email_captcha']) || strtolower($captcha) != strtolower($_SESSION['email_captcha']) || time() > $_SESSION['captcha_expire']){
        echo "<script>alert('验证码错误或已过期');</script>";
        exit;
    }

    // 预处理查询,防止SQL注入
    $sql = "SELECT * FROM logindetails WHERE username = ?";
    $stmt = mysqli_prepare($conn, $sql);
    mysqli_stmt_bind_param($stmt, "s", $username);
    mysqli_stmt_execute($stmt);
    $result = mysqli_stmt_get_result($stmt);
    
    if(mysqli_num_rows($result) === 0){
        // 用户名不存在
        echo "<script>alert('登录失败:用户名或密码错误');</script>";
    } else {
        $row = mysqli_fetch_assoc($result);
        // 生产环境务必用password_verify替代明文对比
        if(password_verify($password, $row['password'])) {
            unset($_SESSION['email_captcha']); // 销毁验证码
            header('Location:index.html');
            exit;
        } else {
            echo "<script>alert('登录失败:用户名或密码错误');</script>";
        }
    }
}

// 处理发送验证码请求
if(isset($_POST['send_captcha'])){
    $username = $_POST['username'];
    $sql = "SELECT email FROM logindetails WHERE username = ?";
    $stmt = mysqli_prepare($conn, $sql);
    mysqli_stmt_bind_param($stmt, "s", $username);
    mysqli_stmt_execute($stmt);
    $result = mysqli_stmt_get_result($stmt);
    
    if(mysqli_num_rows($result) === 0){
        echo "<script>alert('用户名不存在');</script>";
        exit;
    }

    $row = mysqli_fetch_assoc($result);
    $user_email = $row['email'];
    $captcha = rand(100000, 999999); // 生成6位验证码
    $_SESSION['email_captcha'] = $captcha;
    $_SESSION['captcha_expire'] = time() + 300; // 5分钟有效期

    // 发送邮件(生产环境建议用PHPMailer替代原生mail)
    $subject = "登录验证码";
    $message = "您的登录验证码是:$captcha,5分钟内有效。";
    $headers = "From: your-service@example.com"; // 替换为你的发件邮箱

    if(mail($user_email, $subject, $message, $headers)){
        echo "<script>alert('验证码已发送至您的邮箱');</script>";
    } else {
        echo "<script>alert('验证码发送失败,请稍后重试');</script>";
    }
}
?>
</body>
</html>

修复关键点

  • 用mysqli_num_rows()判断查询结果是否存在用户记录,覆盖用户名不存在的场景
  • 统一错误提示为“用户名或密码错误”,避免泄露用户存在性信息(安全优化)
  • 改用预处理语句执行SQL,彻底解决原代码的SQL注入风险
  • 新增密码验证的安全提示:生产环境必须使用password_hash()加密存储密码,用password_verify()验证

二、邮箱验证码功能改造

修改后的HTML登录页

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Login Page</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      margin: 0;
      padding: 0;
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      background-color: #f0f0f0;
    }

    .container {
      width: 300px;
      padding: 20px;
      background-color: #fff;
      border-radius: 8px;
      box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    }

    h2 {
      text-align: center;
    }

    input[type="text"],
    input[type="password"] {
      width: 100%;
      padding: 10px;
      margin: 10px 0;
      border: 1px solid #ccc;
      border-radius: 4px;
      box-sizing: border-box;
    }

    .captcha-group {
      display: flex;
      gap: 10px;
      margin: 10px 0;
    }

    .captcha-group input {
      flex: 1;
    }

    .send-captcha-btn {
      padding: 10px 12px;
      border: none;
      border-radius: 4px;
      background-color: #28a745;
      color: #fff;
      cursor: pointer;
      white-space: nowrap;
    }

    .send-captcha-btn:hover {
      background-color: #218838;
    }

    input[type="submit"] {
      width: 100%;
      padding: 10px;
      border: none;
      border-radius: 4px;
      background-color: #007bff;
      color: #fff;
      cursor: pointer;
    }

    input[type="submit"]:hover {
      background-color: #0056b3;
    }
  </style>
</head>
<body>
  <div class="container">
    <h2>Login</h2>
    <form action="login.php" method="post">
      <input type="text" name="username" placeholder="Username" required>
      <input type="password" name="password" placeholder="Password" required>
      <div class="captcha-group">
        <input type="text" name="captcha" placeholder="验证码" required>
        <button type="button" class="send-captcha-btn" onclick="sendCaptcha()">发送验证码</button>
      </div>
      <input type="submit" value="Login" class="loginBtn" name="login_Btn">
    </form>
  </div>

  <script>
    function sendCaptcha() {
      const username = document.querySelector('input[name="username"]').value;
      if(!username.trim()) {
        alert('请先输入用户名');
        return;
      }
      // AJAX发送请求,避免页面刷新
      const xhr = new XMLHttpRequest();
      xhr.open('POST', 'login.php', true);
      xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
      xhr.send('send_captcha=1&username=' + encodeURIComponent(username));
    }
  </script>
</body>
</html>

功能实现说明

前端部分

  • 添加验证码输入框和“发送验证码”按钮,用Flex布局优化排版
  • 编写AJAX函数sendCaptcha(),在不刷新页面的情况下请求发送验证码
  • 增加用户名输入校验,避免空请求

后端部分

  • 开启session存储验证码及其5分钟有效期
  • 新增send_captcha请求处理逻辑:根据用户名查询用户邮箱,生成随机验证码并发送
  • 登录流程中优先验证验证码的有效性(是否匹配、是否过期)
  • 登录成功后销毁验证码session,防止重复使用

生产环境注意事项

  • 原生mail()函数依赖服务器邮件配置,建议使用PHPMailer、SwiftMailer等专业邮件库提升稳定性
  • 必须对用户密码进行哈希加密存储,禁止明文存储
  • 可添加验证码发送频率限制,防止恶意请求

内容的提问来源于stack exchange,提问作者Methodius5510

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 04:15:57