常見原因
- 字元編碼不一致:JS
md5("admin") 預設 UTF-8,PHP md5($_POST['password']) 若輸入含 BOM 或非 UTF-8 會不同。確保頁面 ``、資料庫連線 `SET NAMES utf8mb4`、PHP 檔案存為 UTF-8 無 BOM。
- 前後端加密方式不同:JS 庫 (如 CryptoJS) 輸出 **Hex 小寫**,PHP
md5() 也輸出 Hex 小寫,但若 JS 用 .toString(CryptoJS.enc.Base64) 或大寫則不一致。
- 鹽值/雜湊次數差異:PHP 若用
md5(md5($pass).$salt) 或多次雜湊,JS 必須完全複製邏輯。
- 傳輸過程被轉義:`$_REQUEST['password']` 可能經過 `magic_quotes_gpc` (已棄用) 或框架自動轉義,導致字串變化。用 `var_dump($_POST['password'])` 對比 JS 端輸出。
排查步驟
// JS 端
var pwd = CryptoJS.MD5("admin").toString(); // 確認輸出
console.log("JS MD5:", pwd);
// PHP 端
error_log("PHP Received: " . $_POST['password']);
error_log("PHP MD5: " . md5($_POST['password']));
安全建議
- **不要在前端直接 MD5**,易被彩虹表破解。應使用 **HTTPS + 後端 bcrypt/argon2** 驗證。
- 若必須前端雜湊,採用 **PBKDF2/Scrypt** 並帶隨機鹽值,後端同算法驗證。
- 防止重放攻擊:登入請求加入 **Nonce/Timestamp + 簽名**。