Học cách tạo captcha bằng ajax & php

Học cách tạo captcha bằng ajax & php là vấn đề được nhiều lập trình viên quan tâm, bởi những kiến thức trên trường lớp là không đủ, vì vậy bài Học cách tạo captcha bằng ajax & php sẽ chia sẻ tới bạn nhiều thông tin hữu ích

Mọi người vẫn hỏi tôi về việc học lập trình nói chung và PHP nói riêng có cần năng khiếu hay quá khó để tiếp cận hay không. Thì tôi có thể trả lời rằng, học lập trình cũng như việc bạn học tiếng Anh hay bất kỳ một ngôn ngữ khác, bởi lập trình...là ngôn ngữ của máy tính, để máy tính đọc và máy tính thực hiện theo yêu cầu của mình, bạn thích là học được.

Nếu như bạn hay lướt web thì bạn sẽ thấy có những website khi bạn đăng ký thành viên hoặc là gửi thông tin liên hệ thì họ sẽ có những mã code cho bạn nhập vào, những đoạn mã này có mục đích là chống spam vì nó được sinh ra ngẫu nhiên. Những đoạn mã như vậy người ta gọi là mã captcha, hay còn gọi là mã chống spam.

Vậy trong bài này tôi sẽ hướng dẫn các bạn tạo một thư viện captcha bằng php  cho riêng mình, đồng thời học cách sử dụng thư viện captcha, cách hiển thị captcha ra form và sử dụng ajax để validate captcha. Ta bắt đầu nhé.

1. Tạo thư viện captcha bằng php

Công việc đầu tiên là bạn phải tạo một thư viện captcha, đây là thư viện mà tôi viết sẵn nên các bạn xem trực tiếp trên nó nhé, tôi chỉ hướng dẫn cách sư dụng.

Bạn tạo file captcha.php với nội dung sau:

 

class Captcha 
{
    var $img_width      =   120;
    var $img_height     =   30; 
         
    var $font_path      =   './fonts'; // đường dẫn đên thư mục file text
    var $fonts          =   array();
    var $font_size      =   15;
     
    var $char_set       =   "ABCDEFGHJKLMNPQRSTUVWXYZ2345689";
    var $char_length    =   5;
     
    var $char_color     =   "#880000,#008800,#000088,#888800,#880088,#008888,#000000";
    var $char_colors    =   array();
     
    var $line_count     =   10;
    var $line_color     =   "#DD6666,#66DD66,#6666DD,#DDDD66,#DD66DD,#66DDDD,#666666";
    var $line_colors    =   array();
         
    var $bg_color       =   '#FFFFFF';
     
    // Khởi tạo cấu hình, hàm này sẽ trả về mã code và hiển thị hình
    function get_and_show_image( $override = array() ) 
        {
                // Override lại thong số config
        if( is_array( $override) )
        {
            foreach ( $override as  $key => $value) {
                                if( isset( $this->$key ))
                                        $this->$key = $value;
            }           
        }
                 
                // Tạo danh sách colors thành một mảng
        $this->line_colors = preg_split("/,\s*?/", $this->line_color );
        $this->char_colors = preg_split("/,\s*?/", $this->char_color );
         
                // Lấy danh sách fonts trong folder được định nghĩa trong biến font_path
        $this->fonts = $this->collect_files( $this->font_path, "ttf");
                 
                // Khởi tạo hình ảnh
        $img = imagecreatetruecolor( $this->img_width, $this->img_height);
        imagefilledrectangle($img, 0, 0, $this->img_width - 1, $this->img_height - 1, $this->gd_color( $this->bg_color ));
         
                 
        // Vẽ hình lung tung cho đời nó tươi mát
        for ($i = 0; $i < $this->line_count; $i++){
            imageline($img,
                rand(0, $this->img_width  - 1),
                rand(0, $this->img_height - 1),
                rand(0, $this->img_width  - 1),
                rand(0, $this->img_height - 1),
                $this->gd_color($this->line_colors[rand(0, count($this->line_colors) - 1)])
            );
                }
             
        // Vẽ code lên hình
        $code = "";
        $y = ($this->img_height / 2) + ( $this->font_size / 2);
         
        for ($i = 0; $i < $this->char_length ; $i++) 
                {
            $color = $this->gd_color( $this->char_colors[rand(0, count($this->char_colors) - 1)] );
            $angle = rand(-30, 30);
            $char = substr( $this->char_set, rand(0, strlen($this->char_set) - 1), 1);
             
            $sel_font = $this->fonts[rand(0, count($this->fonts) - 1)];   
                         
            $font = $this->font_path . "/" . $sel_font;
             
            $x = (intval(( $this->img_width / $this->char_length) * $i) + ( $this->font_size / 2));
            $code .= $char;
             
            imagettftext($img, $this->font_size, $angle, $x, $y, $color, $font, $char);
        }
         
                // Hiển thị ảnh
                header('content-type: image/jpg');
                  
        ImageJPeg( $img);
                 
        return $code;
    }   
         
        // Chuyển color
    function gd_color($html_color) {
        return preg_match('/^#?([\dA-F]{6})$/i', $html_color, $rgb)
          ? hexdec($rgb[1]) : false;
    }
 
        // Lấy danh sách file theo phần mở rộng (ext)
    function collect_files($dir, $ext) 
        {
        if (false !== ($dir = opendir($dir))) 
                {
            $files = array();
 
            while (false !== ($file = readdir($dir)))
                if (preg_match("/\\.$ext\$/i", $file))
                    $files[] = $file;
 
            return $files;
 
        }
                return false;
    }
} 

 

Trong thư viện captcha này bạn cần cấu hình những thông số như sau:

  • Thuộc tính $font_path là nơi chứa những file font chữ của captcha
  • Thuộc tính $img_width là chiều dài của hình ảnh trả về
  • Thuộc tính $img_height là chiều cao của hình ảnh trả về 
  • Thuộc tính $char_length là chiều dài của mã code captcha
  • Thuộc tính $bg_color là mã màu của background, mặc định là màu trắng (FFFFFF),
  • Thuộc tính $font_size là kích thước của chữ in trên hình captcha

Cấu trúc folder sẽ có dạng như sau:

Ở đây bạn chỉ cần chú ý đến folder fonts, đây là folder chứa những file font chữ của captcha,

2. Tạo file hiển thị hình ảnh captcha bằng php

Trong bước này ta sẽ hiển thị hình ảnh captcha thông qua một file PHP, ở file này sẽ import file captcha.php, khởi tạo đối tượng captcha và lưu vào SESSION nhằm mục đích dùng để validate khi người dùng submit form.

Bạn tạo file image.php với nội dung như sau:

 

<?php session_start();
 
require("captcha.php");
$captcha = new Captcha();
$code = $captcha->get_and_show_image();
 
// Lưu code session
$_SESSION['captcha_code'] = $code;
 
?> 

 

Bước này rất đơn giản, quan trọng nhất là ở đoạn code lưu SESSION, nếu ta không lưu thì ta sẽ không biết được mã code hiện tại là bao nhiêu để validate.

3. Tạo form liên hệ hiển thị captcha

Bây giờ tôi sẽ tạo form liên hệ, và để đơn giản tôi chỉ hiển thị một form đơn giản với một nội dung duy nhất đó là content. Bạn tạo file index.php với nội dung như sau:

 

<!DOCTYPE html>
<html>
    <head>
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <script language="javascript" src="http://code.jquery.com/jquery-2.0.0.min.js"></script>
    </head>
    <body style="width: 500px; margin: 0px auto;">
        <form id="mainform" method="post" action="">
            <table border="1" cellspacing="0" cellpadding="5">
                <tr>
                    <td>Nội dung</td>
                    <td><textarea id="content" cols="40" rows="5"></textarea></td>
                </tr>
                <tr>
                    <td>Captcha</td>
                    <td>
                        <img src="image.php" id="img-captcha"/>
                        <input type="button" value="Reload" onclick="$('#img-captcha').attr('src', 'image.php?rand=' + Math.random())" /> <br/>
                        <input type="text" id="captcha" value="" />
                    </td>
                </tr>
                <tr>
                    <td>Captcha</td>
                    <td>
                        <input id="submit" type="submit" value="Lưu" />
                    </td>
                </tr>
            </table>
        </form>
        <script language="javascript">
            $(document).ready(function(){
                $('#submit').click(function()
                {
                    // Lấy dự liệu
                    var data = {
                        content : $('#content').val(),
                        captcha : $('#captcha').val()
                    };
                     
                    // Validate
                    if ($.trim(data.content) == ''){
                        alert('Bạn chưa nhập nội dung');
                    }
                    else if ($.trim(data.captcha) == ''){
                        alert('Bạn chưa nhập captcha');
                    }
                    else{
                         
                        $.ajax({
                            type : 'POST',
                            dataType : 'json',
                            url : 'ajax_validate.php',
                            data : data,
                            success : function (result){
                                if (!result.hasOwnProperty('error')){
                                    alert('Kết quả trả về không phù hợp');
                                }
                                else if (result['error'] == 'success'){
                                    $('#mainform').submit();
                                    alert('Kiểm tra thành công');
                                }
                                else{
                                    if (result['content'] != ''){
                                        alert(result['content']);
                                    }
                                     
                                    if (result['captcha'] != ''){
                                        alert(result['captcha']);
                                    }
                                }
                            },
                            error : function (){
                                alert('Có lỗi xảy ra trong quá trình xử lý');
                            }
                        });
                    }
                    return false;
                });
            });
        </script>
    </body>
</html> 

 

Trong đó đoạn code dưới đây dùng để hiển thị captcha nên trong src của thẻ image tôi có trỏ đên file captcha.php. Và mỗi lần click vào button reload tôi sẽ thay thông số random trên SRC của thẻ captcha với mục đích load lại hình ảnh, vì nếu không làm vậy thì bộ nhớ của trình duyệt sẽ ko gọi đến server để đổi code.

 

<tr>
    <td>Captcha</td>
    <td>
        <img src="image.php" id="img-captcha"/>
        <input type="button" value="Reload" onclick="$('#img-captcha').attr('src', 'image.php?rand=' + Math.random())" /> <br/>
        <input type="text" id="captcha" value="" />
    </td>
</tr> 

 

Đoạn code dưới đây dùng để gửi ajax kiểm tra thông tin người dùng nhập vào:

 

$(document).ready(function(){
    $('#submit').click(function()
    {
        // Lấy dự liệu
        var data = {
            content : $('#content').val(),
            captcha : $('#captcha').val()
        };
 
        // Validate
        if ($.trim(data.content) == ''){
            alert('Bạn chưa nhập nội dung');
        }
        else if ($.trim(data.captcha) == ''){
            alert('Bạn chưa nhập captcha');
        }
        else{
 
            $.ajax({
                type : 'POST',
                dataType : 'json',
                url : 'ajax_validate.php',
                data : data,
                success : function (result){
                    if (!result.hasOwnProperty('error')){
                        alert('Kết quả trả về không phù hợp');
                    }
                    else if (result['error'] == 'success'){
                        $('#mainform').submit();
                        alert('Kiểm tra thành công');
                    }
                    else{
                        if (result['content'] != ''){
                            alert(result['content']);
                        }
 
                        if (result['captcha'] != ''){
                            alert(result['captcha']);
                        }
                    }
                },
                error : function (){
                    alert('Có lỗi xảy ra trong quá trình xử lý');
                }
            });
        }
        return false;
    });
}); 

 

4. Tạo trang nhận request ajax kiểm tra mã captcha bằng php

Bước này ta sẽ tạo một file ajax_validate.php, nội dung của file này sẽ lấy dữ liệu từ đoạn code gửi ajax bên file index.php

 

session_start();
 
// Lấy thông tin
$content = isset($_POST['content']) ? $_POST['content'] : false;
$captcha = isset($_POST['captcha']) ? $_POST['captcha'] : false;
 
// Biến lưu kết quả trả về
$error = array(
    'error'     => 'success',
    'content'   => '',
    'captcha'   => ''
);
 
// Kiểm tra content
if (!$content){
    $error['content'] = 'Bạn chưa nhập nội dung';
    $error['error'] = 'error';
}
 
// Kiểm tra captcha
if (!$captcha){
    $error['captcha'] = 'Bạn chưa nhập captcha';
    $error['error'] = 'error';
}
else if (!isset($_SESSION['captcha_code']) || $_SESSION['captcha_code'] != trim($captcha)) {
    $error['captcha'] = 'Captcha bạn nhập không đúng';
    $error['error'] = 'error';
}
 
// Trả kết quả cho client
die (json_encode($error)); 

 

Trong file này bạn chỉ cần chú ý đến những đoạn code comment mà tôi dùng để kiểm tra mã captcha. Vì ở file image.php tôi lưu code vào SESSION nên ở đây tôi sẽ kiểm tra và gọi session để so sánh thông số rồi trả về kết quả

Chạy lên ta ta sẽ có như hình ảnh dưới đây:

5. Lời kết

Bài này mình chỉ muốn giới thiệu thư viện captcha và cách sử dụng nó như hiển thị captcha, reload capcha,... đồng thời hướng dẫn các bạn cách sử dụng Ajax để validate form. Vì bài khá đơn giản nên mình không sử dụng database để lưu trữ.

Hy vọng với bài viết về Học cách tạo captcha bằng ajax & php đã giải đáp giúp bạn phần nào về kiến thức lập trình PHP. Như tôi đã nói, ngôn ngữ lập trình không quan trọng bằng tư duy giải thuật, tư duy logic để giải quyết vấn đề.

Với những năm trước đây, lập trình viên là một cái nghề khó và kén chọn người học, đồng nghĩa với việc thu nhập hàng tháng của các lập trình viên luôn cao. Còn những năm gần đây, thì lập trình là môn học phổ thông, và ai cũng nên học một ngôn ngữ lập trình nào đó.

Nếu bạn còn bất kỳ câu hỏi nào trong việc học lập trình online, hãy gửi yêu cầu cho tôi qua email hoidapcode.com@gmail.com hoặc để lại comment bên dưới, tôi sẽ giải đáp trong vòng 24 giờ!

Blog hoidapcode.com là blog được tổng hợp tự động các bài học, thông tin về lập trình trên mạng internet. Nếu bạn có ý kiến hoặc đóng góp về bài viết này, hãy liên hệ với tôi!