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

PHP 驗證碼實作指南:從簡單圖形驗證到現代無感驗證

     編輯:PHP 相關知識

驗證碼演進與選型建議

類型安全性使用者體驗適用場景
傳統圖形驗證碼低(易被 OCR/機器學習破解)差(需人工輸入)低風險表單、內部系統
滑塊/點選/旋轉驗證中中登入/註冊頁面
reCAPTCHA v3 / hCaptcha高(行為分析、設備指紋)最佳(無感/極少互動)高風險操作、公開 API、大流量站點
設備指紋 + 風控引擎最高無感金融支付、核心業務

傳統 GD 圖形驗證碼實作(教學用)

注意:僅供學習原理,生產環境強烈建議使用成熟第三方服務。

基礎版:數字/字母組合

<?php
// captcha.php
session_start();
header('Content-Type: image/png');

$width = 120;
$height = 40;
$codeLength = 4;
$charset = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ'; // 排除易混淆字元

$image = imagecreatetruecolor($width, $height);
$bgColor = imagecolorallocate($image, 240, 240, 240);
$textColor = imagecolorallocate($image, 50, 50, 50);
$noiseColor = imagecolorallocate($image, 180, 180, 180);

imagefilledrectangle($image, 0, 0, $width, $height, $bgColor);

// 干擾線
for ($i = 0; $i < 5; $i++) {
    imageline($image, mt_rand(0, $width), mt_rand(0, $height), mt_rand(0, $width), mt_rand(0, $height), $noiseColor);
}

// 干擾點
for ($i = 0; $i < 50; $i++) {
    imagesetpixel($image, mt_rand(0, $width), mt_rand(0, $height), $noiseColor);
}

// 生成驗證碼
$code = '';
for ($i = 0; $i < $codeLength; $i++) {
    $code .= $charset[mt_rand(0, strlen($charset) - 1)];
    $x = 20 + $i * 22 + mt_rand(-2, 2);
    $y = 8 + mt_rand(-2, 2);
    imagestring($image, 5, $x, $y, $code[$i], $textColor);
}

$_SESSION['captcha_code'] = strtoupper($code);
imagepng($image);
imagedestroy($image);

前端整合與驗證

<!-- HTML -->
<img id="captchaImg" src="captcha.php" alt="驗證碼" style="cursor:pointer;vertical-align:middle" title="點擊更換">
<input type="text" name="captcha" id="captchaInput" placeholder="輸入驗證碼">

<script>
document.getElementById('captchaImg').addEventListener('click', function() {
    this.src = 'captcha.php?' + Date.now(); // 防快取
});
</script>
<?php
// verify.php
session_start();
$input = isset($_POST['captcha']) ? strtoupper(trim($_POST['captcha'])) : '';
$stored = $_SESSION['captcha_code'] ?? '';

if ($input === $stored && $input !== '') {
    echo '驗證通過';
    unset($_SESSION['captcha_code']); // 一次性使用
} else {
    echo '驗證碼錯誤或已過期';
}

進階:整合 reCAPTCHA v3(推薦生產環境)

  1. 至 Google reCAPTCHA 管理後台 註冊網站,取得 Site Key 與 Secret Key。
  2. 前端引入 JS 並在關鍵動作執行 grecaptcha.execute() 取得 token。
  3. 後端驗證 token 與分數(建議閾值 0.5)。
<!-- 前端 -->
<script src="https://www.google.com/recaptcha/api.js?render=YOUR_SITE_KEY"></script>
<script>
function submitWithRecaptcha(action) {
    grecaptcha.ready(function() {
        grecaptcha.execute('YOUR_SITE_KEY', {action: action}).then(function(token) {
            document.getElementById('recaptcha_token').value = token;
            document.getElementById('recaptcha_action').value = action;
            document.forms[0].submit();
        });
    });
}
</script>
<form method="POST">
    <input type="hidden" name="recaptcha_token" id="recaptcha_token">
    <input type="hidden" name="recaptcha_action" id="recaptcha_action">
    <button type="button" onclick="submitWithRecaptcha('login')">登入</button>
</form>
<?php
// 後端驗證
$secret = 'YOUR_SECRET_KEY';
$token = $_POST['recaptcha_token'] ?? '';
$action = $_POST['recaptcha_action'] ?? '';
$remoteIp = $_SERVER['REMOTE_ADDR'];

$response = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=$secret&response=$token&remoteip=$remoteIp");
$result = json_decode($response, true);

if ($result['success'] && $result['action'] === $action && $result['score'] >= 0.5) {
    // 驗證通過,執行業務邏輯
} else {
    // 驗證失敗,記錄日誌、要求二次驗證或封鎖
    error_log('reCAPTCHA failed: ' . json_encode($result));
}

安全加固建議

  • 限制嘗試次數:同一 IP/帳號 5 分鐘內失敗超過 5 次暫時封鎖。
  • 驗證碼一次性:驗證成功或失敗後立即銷毀 Session 中的驗證碼。
  • HTTPS 傳輸:防止驗證碼在傳輸過程被攔截。
  • 無障礙支援:提供音頻驗證碼或替代驗證方式。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved