MIS 腳印 logo

MIS 腳印

記錄 IT 學習的軌跡

Google 我不是機器人 reCAPTCHA Ajax 驗證碼教學範例 for PHP

使用 Google 提供的「我不是機器人」reCAPTCHA 點擊驗證方式,並個別以傳統表單、Ajax JavaScript、Ajax jQuery 實作的教學範例。

Google reCAPTCHA
下載範例

Google 提供的「我不是機器人」點擊驗證方式,不僅可有效防止自動提交機器人 robot 與暴力破解取得帳號、密碼,也成功取代舊有的「圖形」輸入驗證碼方式,大大提升了使用者體驗。

註冊

使用前必須先到 reCAPTCHA 申請 > 點擊右上角的「Get reCAPTCHA」> 資料填寫完後點擊「Register」。

  • Label:輸入網站的名稱(自訂)
  • Domains:輸入網域名稱(使用換行可設定多個)
  • Send alerts to owners:當有問題時會主動通知您

使用說明

Keys

  • Site Key(公鑰):用在「客戶端」HTML,提供 reCAPTCHA 驗證碼服務給使用者
  • Secret key(密鑰):用在「伺服器端」,網站與 Google 之間的通訊

client-side integration

「客戶端」的使用說明。

  • <script>:Google reCAPTCHA 的 API js 檔
  • <div>:reCAPTCHA 小工具出現的位置

Server side integration

「伺服器端」的使用說明。

細節說明與配置

點擊 The reCAPTCHA documentation site 進入更多細節說明與配置。

這邊可看到有二種版本:

  • Version 1.0 舊版:「圖形」輸入驗證碼方式
  • Version 2.0 新版:「我不是機器人」點擊驗證方式

點擊「Introduction」> 下載 Google 已建立好的 reCAPTCHA PHP 類別範例,點擊 PHP

點擊「Clone or download」>「Download ZIP」下載檔案。

程式範例

建立目錄 includes,並將下載的 recaptcha-master.zip > src 目錄下的檔案解壓縮至 includes,在選擇以下其中一種方式,新增的檔案與 includes 放置在同目錄下。

傳統表單

傳送 – index.php:

<!DOCTYPE html>
<html lang="zh-Hant-TW">
<head>
    <meta charset="UTF-8">
    <title>傳統表單 | reCAPTCHA 範例 - 傳送</title>

    <!-- Google reCAPTCHA icon -->
    <link rel="shortcut icon" href="//www.gstatic.com/recaptcha/admin/favicon.ico" type="image/x-icon"/>
</head>
<body>
    
    <h1>reCAPTCHA 範例 - 傳送</h1>

    <?php
    // 註冊或查詢你的 API Keys: https://www.google.com/recaptcha/admin
    $siteKey = '你的 Site key';

    // 所有支援的語系: https://developers.google.com/recaptcha/docs/language
    $lang = 'zh-TW';

    // 如果未填入 API Key
    if ($siteKey === '') {
        echo '
    <h2>新增 API key</h2>
    <p>如果沒有的話可以去這申請 <a href="https://www.google.com/recaptcha/admin">Google reCAPTCHA</a>。</p>';
    } else {
        echo '
    <p>點擊「我不是機器人」後,送出表單‧</p>

    <form action="captcha.php" method="post">
        <fieldset>
            <legend>一個範例</legend>

            <label>
                範例 input A: <input type="text" name="ex-a" value="foo">
            </label>
            <br /><br />

            <label>
                範例 input B: <input type="text" name="ex-b" value="bar">
            </label>
            <br /><br />

            <div class="g-recaptcha" data-sitekey="' . $siteKey . '"></div>
            <script type="text/javascript" src="https://www.google.com/recaptcha/api.js?hl=' . $lang . '"></script>
            <br />

            <input type="submit" value="送出" />
        </fieldset>
    </form>';
    }
    ?>

</body>
</html>

接收 – captcha.php:

<!DOCTYPE html>
<html lang="zh-Hant-TW">
<head>
    <meta charset="UTF-8">
    <title>傳統表單 | reCAPTCHA 範例 - 接收</title>

    <!-- Google reCAPTCHA icon -->
    <link rel="shortcut icon" href="//www.gstatic.com/recaptcha/admin/favicon.ico" type="image/x-icon"/>
</head>
<body>
    
    <h1>reCAPTCHA 範例 - 接收</h1>

    <?php
    require_once __DIR__ . '/includes/recaptcha/autoload.php';

    // 註冊或查詢你的 API Keys: https://www.google.com/recaptcha/admin
    $secret = '你的 Secret key';

    if (isset($_POST['g-recaptcha-response'])) {
        $recaptcha = new \ReCaptcha\ReCaptcha($secret);
        // 確認驗證碼與 IP
        $resp = $recaptcha->verify($_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR']);

        $var = var_export($_POST, true);

        echo '
    <h2>POST data</h2>
    <pre>' . $var . '</pre>';

        // 確認正確
        if ($resp->isSuccess()) {
            echo '
    <h2>Success!</h2>
    <p>確認正確</p>
    <a href="index.php">在試一次</a>';
        }
        // 確認失敗
        else {
            echo '
    <h2>確認失敗</h2>
    <p>返回以下錯誤。</p>';

            foreach ($resp->getErrorCodes() as $code) {
                echo '<p>' . $code . '</p> ';
            }

            echo '
    <p>檢查引用的錯誤代碼 <a href="https://developers.google.com/recaptcha/docs/verify#error-code-reference">https://developers.google.com/recaptcha/docs/verify#error-code-reference</a>。</p>
    <p><strong>Note:</strong> 程式錯誤,使用者沒有完成 reCAPTCHA 驗證碼。</p>
    <a href="index.php">在試一次</a>';
        }
    }
    ?>

</body>
</html>

Ajax JavaScript

傳送 – index.php:

<?php
// 註冊或查詢你的 API Keys: https://www.google.com/recaptcha/admin
$siteKey = '你的 Site key';

// 所有支援的語系: https://developers.google.com/recaptcha/docs/language
$lang = 'zh-TW';
?>

<!DOCTYPE html>
<html lang="zh-Hant-TW">
<head>
    <meta charset="UTF-8">
    <title>Ajax JavaScript | reCAPTCHA 範例</title>
    
    <script type="text/javascript" src="https://www.google.com/recaptcha/api.js?hl=<?php echo $lang; ?>&onload=onloadCallback&render=explicit" async defer></script>
    <script type="text/javascript">
    var verifyCallback = function(response) {
        // 如果 JavaScript 驗證成功
        if (response) {
            // 發送 Ajax 查詢請求並處理
            var request = new XMLHttpRequest();
            request.open("POST", "captcha.php");

            // POST 參數須使用 send() 發送
            var data = "g-recaptcha-response=" + response;

            // POST 請求必須設置表頭在 open() 下面,send() 上面
            request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            request.send(data);

            request.onreadystatechange = function() {
                // 伺服器請求完成
                if (request.readyState === 4) {
                    // 伺服器回應成功
                    if (request.status === 200) {
                        var type = request.getResponseHeader("Content-Type");   // 取得回應類型

                        // 判斷回應類型,這裡使用 JSON
                        if (type.indexOf("application/json") === 0) {   
                            var data = JSON.parse(request.responseText);
                            var success = document.getElementById('success');

                            // 如果 PHP 驗證成功
                            if (data.success) success.innerHTML = '驗證成功';
                            else success.innerHTML = '驗證失敗';
                        }
                    } else {
                        alert("發生錯誤" + request.status);
                    }
                }
            }
        }
    };

    /*
     * recaptcha API 參考 https://developers.google.com/recaptcha/docs/display
     */
    var onloadCallback = function() {
        grecaptcha.render(
            'my-widget', {                              // widget 驗證碼視窗在 id="my-widget" 顯示
                'sitekey' : '<?php echo $siteKey; ?>',  // API Key
                'callback' : verifyCallback,            // 要呼叫的回調函式
                'theme' : 'dark'                        // 主題
            }
        );
    };
    </script>

    <!-- Google reCAPTCHA icon -->
    <link rel="shortcut icon" href="//www.gstatic.com/recaptcha/admin/favicon.ico" type="image/x-icon"/>
</head>
<body>
    
    <!-- 顯示驗證成功與否 -->
    <h1 id="success"></h1>

    <!-- reCAPTCHA 小工具出現的位置 -->
    <!-- POSTs back to the page's URL upon submit with a g-recaptcha-response POST parameter. -->
    <div id="my-widget"></div>

</body>
</html>

接收 – captcha.php:

<?php
header('Content-type: application/json');

require_once __DIR__ . '/includes/recaptcha/autoload.php';

// 註冊或查詢你的 API Keys: https://www.google.com/recaptcha/admin
$secret = '你的 Secret key';

if (isset($_POST['g-recaptcha-response'])) {
    $recaptcha = new \ReCaptcha\ReCaptcha($secret);
    // 確認驗證碼與 IP
    $resp = $recaptcha->verify($_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR']);

    $var = var_export($_POST, true);

    // 確認正確
    if ($resp->isSuccess()) echo json_encode(array('success' => true));
}

Ajax jQuery

傳送 – index.php:

<?php
// 註冊或查詢你的 API Keys: https://www.google.com/recaptcha/admin
$siteKey = '你的 Site key';

// 所有支援的語系: https://developers.google.com/recaptcha/docs/language
$lang = 'zh-TW';
?>

<!DOCTYPE html>
<html lang="zh-Hant-TW">
<head>
    <meta charset="UTF-8">
    <title>Ajax jQuery | reCAPTCHA 範例</title>
    
    <!-- Google jQuery -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    
    <script type="text/javascript" src="https://www.google.com/recaptcha/api.js?hl=<?php echo $lang; ?>&onload=onloadCallback&render=explicit" async defer></script>
    <script type="text/javascript">
    /*
     * recaptcha API 參考 https://developers.google.com/recaptcha/docs/display
     */
    var verifyCallback = function(response) {
        // 如果 JavaScript 驗證成功
        if (response) {
            $.post('captcha.php', { 'g-recaptcha-response': response }, function(data, status) {
                // 如果 PHP 驗證成功
                if (status == 'success') $('#success').text('驗證成功');
                else $('#success').text('驗證失敗');
            });
        }
    };

    var onloadCallback = function() {
        grecaptcha.render(
            'my-widget', {                              // widget 驗證碼視窗在 id="my-widget" 顯示
                'sitekey' : '<?php echo $siteKey; ?>',  // API Key
                'callback' : verifyCallback,            // 要呼叫的回調函式
                'theme' : 'dark'                        // 主題
            }
        );
    };
    </script>

    <!-- Google reCAPTCHA icon -->
    <link rel="shortcut icon" href="//www.gstatic.com/recaptcha/admin/favicon.ico" type="image/x-icon"/>
</head>
<body>
    
    <!-- 顯示驗證成功與否 -->
    <h1 id="success"></h1>

    <!-- reCAPTCHA 小工具出現的位置 -->
    <!-- POSTs back to the page's URL upon submit with a g-recaptcha-response POST parameter. -->
    <div id="my-widget"></div>

</body>
</html>

接收 – captcha.php:

<?php
header('Content-type: application/json');

require_once __DIR__ . '/includes/recaptcha/autoload.php';

// 註冊或查詢你的 API Keys: https://www.google.com/recaptcha/admin
$secret = '你的 Secret key';

if (isset($_POST['g-recaptcha-response'])) {
    $recaptcha = new \ReCaptcha\ReCaptcha($secret);
    // 確認驗證碼與 IP
    $resp = $recaptcha->verify($_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR']);

    $var = var_export($_POST, true);

    // 確認正確
    if ($resp->isSuccess()) echo json_encode(array('success' => true));
}

參考

在〈Google 我不是機器人 reCAPTCHA Ajax 驗證碼教學範例 for PHP〉中有 5 則留言

發表迴響