首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP+JS+MySQL 仿 WebQQ 專案實戰(二):暱稱、密碼、確認密碼即時驗證實作

     編輯:PHP 相關知識

前言

承接上一篇郵箱驗證,本文實作註冊表單中其餘核心欄位的即時驗證:暱稱(長度、字元限制)、密碼(強度、規則)、確認密碼(一致性)。這些驗證多為純前端邏輯,無需 AJAX 請求,回應極速,是表單優化的關鍵環節。

一、驗證需求規範

欄位規則錯誤訊息範例
暱稱必填、1-16 字元、允許中英數底線暱稱不能為空 / 不要超過 16 字元 / 僅限中英數底線
密碼必填、6-16 字元、至少包含字母和數字密碼不能為空 / 密碼長度 6-16 字元 / 必須包含字母和數字
確認密碼必填、與密碼完全一致請確認密碼 / 兩次輸入不一致

二、HTML 表單結構

<form id="registerForm" action="register.php" method="post" novalidate>
    <!-- 郵箱欄位(上一篇) -->
    
    <div class="form-group">
        <label for="nickname">暱稱:</label>
        <input type="text" id="nickname" name="nickname"
               onblur="checkNickname(this.value)"
               oninput="checkNickname(this.value)"
               placeholder="1-16 字元,中英數底線">
        <span id="nicknameError" class="error-msg"></span>
    </div>
    
    <div class="form-group">
        <label for="password">密碼:</label>
        <input type="password" id="password" name="password"
               onblur="checkPassword(this.value)"
               oninput="checkPassword(this.value)"
               placeholder="6-16 字元,含字母和數字">
        <span id="passwordError" class="error-msg"></span>
        <div id="passwordStrength" class="strength-bar"><div class="strength-fill"></div></div>
    </div>
    
    <div class="form-group">
        <label for="confirmPassword">確認密碼:</label>
        <input type="password" id="confirmPassword" name="confirm_password"
               onblur="checkConfirmPassword(this.value)"
               oninput="checkConfirmPassword(this.value)"
               placeholder="再次輸入密碼">
        <span id="confirmPasswordError" class="error-msg"></span>
    </div>
    
    <button type="submit" id="submitBtn" disabled>註冊</button>
</form>

三、JavaScript 統一驗證框架

<script>
// 狀態管理
const validationState = {
    email: false,
    nickname: false,
    password: false,
    confirmPassword: false
};

// DOM 元素快取
const els = {
    nicknameError: document.getElementById('nicknameError'),
    passwordError: document.getElementById('passwordError'),
    confirmPasswordError: document.getElementById('confirmPasswordError'),
    passwordStrength: document.getElementById('passwordStrength'),
    submitBtn: document.getElementById('submitBtn')
};

// 統一更新提交按鈕狀態
function updateSubmitState() {
    const allValid = Object.values(validationState).every(v => v === true);
    els.submitBtn.disabled = !allValid;
    els.submitBtn.style.opacity = allValid ? '1' : '0.6';
    els.submitBtn.style.cursor = allValid ? 'pointer' : 'not-allowed';
}

// 顯示錯誤/成功訊息
function showMessage(el, message, isError = true) {
    el.innerHTML = `${message}`;
}

四、暱稱驗證實作


function checkNickname(value) {
    const trimmed = value.trim();
    
    if (!trimmed) {
        showMessage(els.nicknameError, '* 暱稱不能為空!');
        validationState.nickname = false;
    } else if (trimmed.length > 16) {
        showMessage(els.nicknameError, '* 暱稱不能超過 16 個字元!');
        validationState.nickname = false;
    } else if (!/^[\u4e00-\u9fa5a-zA-Z0-9_]+$/.test(trimmed)) {
        showMessage(els.nicknameError, '* 暱稱僅限中文、英文、數字和底線!');
        validationState.nickname = false;
    } else {
        showMessage(els.nicknameError, '* 暱稱可用!', false);
        validationState.nickname = true;
    }
    
    updateSubmitState();
}

五、密碼驗證與強度顯示實作


function checkPassword(value) {
    // 重置確認密碼狀態(密碼變更需重新確認)
    validationState.confirmPassword = false;
    showMessage(els.confirmPasswordError, '* 請確認密碼');
    document.getElementById('confirmPassword').value = '';
    
    if (!value) {
        showMessage(els.passwordError, '* 密碼不能為空!');
        validationState.password = false;
        updateStrengthBar(0);
    } else if (value.length < 6 || value.length > 16) {
        showMessage(els.passwordError, '* 密碼長度必須為 6-16 個字元!');
        validationState.password = false;
        updateStrengthBar(1);
    } else if (!/[a-zA-Z]/.test(value) || !/[0-9]/.test(value)) {
        showMessage(els.passwordError, '* 密碼必須包含字母和數字!');
        validationState.password = false;
        updateStrengthBar(2);
    } else {
        showMessage(els.passwordError, '* 密碼可用!', false);
        validationState.password = true;
        updateStrengthBar(calculateStrength(value));
    }
    
    updateSubmitState();
}

/**
 * 密碼強度計算(0-4 級)
 * @param {string} pwd
 * @returns {number} 0:極弱 1:弱 2:中 3:強 4:極強
 */
function calculateStrength(pwd) {
    let score = 0;
    // 長度
    if (pwd.length >= 8) score++;
    if (pwd.length >= 12) score++;
    // 字元多樣性
    if (/[a-z]/.test(pwd)) score++;
    if (/[A-Z]/.test(pwd)) score++;
    if (/[0-9]/.test(pwd)) score++;
    if (/[^a-zA-Z0-9]/.test(pwd)) score++; // 特殊字元
    return Math.min(score, 4);
}

/**
 * 更新強度條 UI
 * @param {number} level 0-4
 */
function updateStrengthBar(level) {
    const colors = ['#e74c3c', '#e67e22', '#f39c12', '#2ecc71', '#27ae60'];
    const labels = ['極弱', '弱', '中等', '強', '極強'];
    
    const fill = document.querySelector('.strength-fill');
    if (fill) {
        fill.style.width = `${(level / 4) * 100}%`;
        fill.style.backgroundColor = colors[level] || colors[0];
        fill.setAttribute('title', labels[level] || '');
    }
}

六、確認密碼驗證實作


function checkConfirmPassword(value) {
    const password = document.getElementById('password').value;
    
    if (!value) {
        showMessage(els.confirmPasswordError, '* 請確認密碼!');
        validationState.confirmPassword = false;
    } else if (value !== password) {
        showMessage(els.confirmPasswordError, '* 兩次輸入的密碼不一致!');
        validationState.confirmPassword = false;
    } else {
        showMessage(els.confirmPasswordError, '* 密碼輸入一致!', false);
        validationState.confirmPassword = true;
    }
    
    updateSubmitState();
}

七、CSS 樣式建議

.form-group { margin-bottom: 15px; }
.form-group label { display: block; margin-bottom: 5px; font-weight: bold; }
.form-group input { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box; }
.form-group input:focus { border-color: #3498db; outline: none; box-shadow: 0 0 5px rgba(52,152,219,0.3); }
.error-msg { display: block; margin-top: 5px; font-size: 12px; min-height: 16px; }
.strength-bar { height: 4px; background: #ecf0f1; border-radius: 2px; margin-top: 8px; overflow: hidden; }
.strength-fill { height: 100%; width: 0%; transition: width 0.3s, background-color 0.3s; }
button[type="submit"] { width: 100%; padding: 12px; background: #3498db; color: white; border: none; border-radius: 4px; font-size: 16px; transition: opacity 0.3s; }
button[type="submit"]:hover:not(:disabled) { background: #2980b9; }
button[type="submit"]:disabled { opacity: 0.6; cursor: not-allowed; }

八、後端二次驗證(PHP)

鐵律:前端驗證只為用戶體驗,後端驗證才是安全防線!

<?php
// register.php 核心驗證邏輯
function validateRegistration(array $data): array {
    $errors = [];
    
    // 郵箱(含唯一性檢查)
    if (empty($data['email'])) {
        $errors['email'] = '郵箱不能為空';
    } elseif (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
        $errors['email'] = '郵箱格式不正確';
    } elseif (strlen($data['email']) > 100) {
        $errors['email'] = '郵箱過長';
    } else {
        // 檢查資料庫唯一性...
    }
    
    // 暱稱
    if (empty($data['nickname'])) {
        $errors['nickname'] = '暱稱不能為空';
    } elseif (strlen($data['nickname']) > 16) {
        $errors['nickname'] = '暱稱不能超過 16 字元';
    } elseif (!preg_match('/^[\p{Han}a-zA-Z0-9_]+$/u', $data['nickname'])) {
        $errors['nickname'] = '暱稱僅限中英數底線';
    }
    
    // 密碼
    if (empty($data['password'])) {
        $errors['password'] = '密碼不能為空';
    } elseif (strlen($data['password']) < 6 || strlen($data['password']) > 16) {
        $errors['password'] = '密碼長度必須 6-16 字元';
    } elseif (!preg_match('/[a-zA-Z]/', $data['password']) || !preg_match('/[0-9]/', $data['password'])) {
        $errors['password'] = '密碼必須包含字母和數字';
    }
    
    // 確認密碼
    if ($data['password'] !== ($data['confirm_password'] ?? '')) {
        $errors['confirm_password'] = '兩次密碼輸入不一致';
    }
    
    return $errors;
}

// 使用範例
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $errors = validateRegistration($_POST);
    if (empty($errors)) {
        // 密碼雜湊
        $hash = password_hash($_POST['password'], PASSWORD_BCRYPT);
        // 寫入資料庫...
        echo '註冊成功!';
    } else {
        // 回傳錯誤給前端顯示
        foreach ($errors as $field => $msg) {
            echo "";
        }
    }
}

九、總結與最佳實踐

  1. 分層驗證:前端即時回饋(UX)+ 後端嚴格把關(安全)
  2. 即時反饋:使用 `oninput` 即時驗證,`onblur` 最終確認
  3. 狀態管理:集中管理驗證狀態,控制提交按鈕可用性
  4. 密碼強度視覺化:強度條引導用戶設定更安全密碼
  5. 密碼雜湊:後端務必使用 `password_hash()` + `PASSWORD_BCRYPT`
  6. CSRF 保護:表單加入 CSRF Token,後端驗證

掌握這套驗證體系,能構建既安全又友好的註冊/登入表單,為用戶體驗與系統安全雙贏奠定基礎!

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved