2016/12/18

Google reCAPTCHA On Codeigniter

前言

為了避免網站被 robot 掃模做重複性的動作,例如加入會員,申請忘記密碼等等,我們會放一個必須人為輸入的欄位並且讓 robot 難以辨識破解,常見的會有文字以及數字的圖像化輸入,但有的機器人如果拿到規律以及足夠的樣本,純文字的輸入方式是可能被破解的,Google 出的 reCaptcha 屬於圖像化的選擇驗證,不管是排列位置或是種類的多樣性都難以去破解,在這邊示範一下怎麼整合 ci 使用

實做

套件安裝

首先安裝 google/recaptcha 這個套件,我在 codeigniter 上有使用 composer,在 config/config.php 下可以打開,使用方法跟在 Laravel 上一樣

程式碼

application/controllers/Recaptcha.php
<?php

defined('BASEPATH') OR exit('No direct script access allowed');

class Recaptcha extends CI_Controller
{
    public function index()
    {
        $this->load->helper('form');
        $this->load->helper('url');
        $this->load->view('recaptcha/form');
    }

    public function result()
    {
        $this->load->library('form_validation');

        $status = 'done';
        $message = 'done';
        $secret = '6LfsIQ8UAAAAAOveAzcFb6A_3Yiv_QdfR-qo5qld';

        try {
            $this->form_validation->set_rules('username', 'username', 'required');
            $this->form_validation->set_rules('g-recaptcha-response', 'captcha', 'required');

            if (!$this->form_validation->run()) {
                throw new Exception(validation_errors(null, null));
            }

            $gRecaptchaResponse = $this->input->post('g-recaptcha-response');
            $remoteIp = $this->input->ip_address();
            $recaptcha = new \ReCaptcha\ReCaptcha($secret);
            $resp = $recaptcha->verify($gRecaptchaResponse, $remoteIp);

            if (!$resp->isSuccess()) {
                $errors = $resp->getErrorCodes();
                throw new Exception(current($errors));
            }
        } catch (Exception $e) {
            $status = 'fail';
            $message = $e->getMessage();
        }

        $this->output
            ->set_content_type('application/json')
            ->set_output(json_encode(compact('status', 'message')));
    }
}
application/views/recaptcha/form.php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>reCAPTCHA Demo</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script src='https://www.google.com/recaptcha/api.js'></script>
    <script type="text/javascript" charset="utf-8">
    var baseUrl = "<?php echo base_url(); ?>";

    $(function() {
        $('#recaptcha_form').on('submit', function() {
            var data = $(this).serialize();

            $.post(baseUrl + 'recaptcha/result', data, function(response) {
                alert(response.message);

                if (response.status === 'done') {
                    grecaptcha.reset();
                }
            }, 'json');

            return false;
        });
    });
    </script>
</head>
<body>
    <?php echo form_open('recaptcha/result', ['id' => 'recaptcha_form']); ?>
    <div><?php echo form_input('uername', 'chan'); ?></div>
    <div class="g-recaptcha" data-sitekey="6LfsIQ8UAAAAAFmYCwSLpfKgWtqK1SlVfMcPn2Q6"></div>
    <div><?php echo form_submit('go', 'go'); ?></div>
    <?php echo form_close(); ?>
</body>
</html>

使用 reCAPTCHA 要先去申請 key 跟 secret,這部份我就不講解了,這份程式碼主要功能就是驗證是否有輸入 username 以及 reCAPTCHA,有的話再進一步驗證 captcha 正確性,如果你不想使用套件的錯誤訊息,那一旦報錯你只要顯示 captcha 錯誤即可,有些表單送出後不一定會換頁,所以我加了個 script 如果偵測到這次的行為正確的時候 refresh 一個新的 captcha,語法的使用時機可以看使用者的使用情況去調整搭配

沒有留言: