Trang

Thứ Năm, 18 tháng 7, 2013

Zend_Captcha [Zend Framework]

Việc cho người dùng thao tác lên cơ sở dữ liệu chứa nhiều rủi ro, có thể các đoạn mã độc được chèn vào làm ngập lụt cơ sở dữ liệu hay các SQL injection. Một trong các giải pháp hạn chế rủi ro này là dùng Captcha.
I. LÝ THUYẾT

1. Khởi tạo đối tượng
$captcha = new Zend_Captcha_Images();

2. Cài đặt các thông số
$captcha->setTimeout()
            ->setWordLen()
            ->setHeight()
            ->setWidth()
            ->setImgDir("đường_dẫn")
            ->setImgUrl("đường_dẫn")
            ->setFont("đường_dẫn")
            ->setFontsize();

- setTimeout('300') : đặt thời gian tồn tại của session chứa mã xác nhận, tính bằng giây
- setWordLen('6') : số kí tự xuất hiện trên hình captcha
- setHeight('70') : chiều cao của hình captcha
- setWidth('150') : chiều rộng của hình captcha
- setImgDir(APPLICATION_PATH.'/../public/captcha/images/'): đường dẫn tuyệt đối tới thư mục chứa hình captcha
- setImgUrl(HOST_PATH.'/public/captcha/images/'): đường dẫn trong scr = " " của hình captcha trong View
- setFont('./public/captcha/images/font/arial.ttf'): đường dẫn tới thư mục chứa Font chữ captcha
- setFontsize('30') : kich thước cỡ chữ

3. Tạo hình captcha và truyền qua View
$captcha->generate();
$this->view->imgCaptcha= $captcha->render();

4. Lấy IdCaptcha và truyền qua View
$idCaptcha = $captcha->getId();
$this->view->idCaptcha=$idCaptcha;

IdCaptcha chính là tên file hình captcha



Ví dụ: IdCaptcha của hình trên là 9c879c33e0d77e0cc5d6843775d9e95d
Mỗi một hình captcha có một IdCaptcha. IdCaptcha dùng để tạo một Session cho hình captcha đó. Sau đó mình lấy mã xác nhận trên hình làm giá trị cho Session này.

5. Tạo Session chứa mã xác nhận
$sessionCaptcha = new Zend_Session_Namespace('Zend_Form_Captcha_'.$captcha->getId());
$sessionCaptcha->word = $captcha->getWord();

Dòng đầu tiên mình tạo một Session với Namespace có chứa IdCaptcha của hình captcha
Dòng thứ hai là mình lấy mã xác nhận trên hình captcha qua phương thức getWord() rồi gán mã xác nhận đó cho Session

6. Kiểm tra

Mình chỉ cần so sánh mã xác nhận của Session với mã xác nhận của người dùng được gửi khi Submit, nếu trùng thì cho qua, ngược lại thì tạo một hình captcha mới.

Để lấy mã xác nhận của Session thì mình cần phải biết IdCaptcha của hình captcha chứa mã xác nhận đó

Do vậy khi Submit, ngoài việc truyền mã xác nhận do người dùng đánh, thì mình truyền thêm IdCaptcha của hình captcha đó nữa. Mình nên để IdCaptcha đó trong một hidden field.

Ví dụ
// Khi submit

// Lấy IdCaptcha
$idCaptcha = $this->_request->getPost('idCaptcha');
// Khởi tạo Session cho IdCaptcha này và lấy mã xác nhận được lưu trên Session
$sessionCaptcha = new Zend_Session_Namespace('Zend_Form_Captcha_'.$idCaptcha);
$sessionWord = $sessionCaptcha->word;
// Lấy mã xác nhận được truyền
$getMaCaptcha = $this->_request->getPost('maCaptcha');
// So sánh
if( $getMaCaptcha == $sessionWord )
 {
      echo "You Passed";
 }else{
           //Tạo một hình captcha mới.
           echo "You Fail";
        }

II. Viết ứng dụng sử dụng Captcha

Mình sẽ tạo một hình captcha với mã xác nhận trên đó. Phía dưới có một textfield để gõ mã xác nhận. Khi CheckCaptcha, nếu đúng mã xác nhận thì thông báo "You Passed", ngược lại tạo một hình captcha mới và thông báo là "You Fail".



 
 Bước 1: Tạo một action là captchaAction() với nội dung
public function captchaAction()
  {
     // Khởi tạo đối tượng zend captcha
     $captcha = new Zend_Captcha_Image();
     
     if( !$this->_request->isPost())
      { // Chạy lần đầu
         // Cài đặt các thông số
         $captcha->setTimeout('300')
                 ->setWordLen('6')
                 ->setHeight('70')
                 ->setWidth('150')
                 ->setFontsize('30')
                 ->setImgDir(APPLICATION_PATH.'/../public/default/captcha/images/')
                 ->setImgUrl(HOST_PATH.'/public/default/captcha/images/')// set đường dẫn cho hình captcha trong <img src="đường_dẫn">
                 ->setFont('./public/default/captcha/font/arial.ttf');
         // Tạo một hình captcha 
         $captcha->generate();
         // Truyền hình captcha vừa tạo qua View
         $this->view->imageCaptcha = $captcha->render();
         // Truyền Idcaptcha qua view (để sau khi submit mình lấy Id này để lấy mã xác nhận chứa trong Session)
         $this->view->idCaptcha = $captcha->getId(); // Id này chứa trong hidden field bên View
         
         /* Tạo Sesion cho hình captcha vừa tạo.
            Phương thức $captcha->getId là lấy Id của hình, mà Id của hình thì chính là tên hình 
         */
         $sessionCaptcha = new Zend_Session_Namespace('Zend_Form_Captcha_'.$captcha->getId());
         
         // Truyền giá trị là mã xác nhận vào Session
         $sessionCaptcha->word = $captcha->getWord(); // $captcha->getWord là lấy mã xác nhận trên hình
         
      }else{ // Khi Submit
             // Kiểm tra captcha 
             // 1. Lấy Idcaptcha
             $idCaptcha = $this->_request->getPost('idCaptcha');
             // 2. Lấy mã xác nhận trong Session qua Idcaptcha
              $sessionCaptcha = new Zend_Session_Namespace('Zend_Form_Captcha_'.$idCaptcha);
              $captchaWord = $sessionCaptcha->word;
             // 3. Lấy mã xác nhận do người dùng nhập
              $getMaCaptcha = $this->_request->getPost('maCaptcha');
             // 4. So sánh hai mã với nhau
             if( $captchaWord == $getMaCaptcha )
               {
                  $this->view->message= "You Passed" ;  
               }else{ 
                      // Nếu sai thì hiện lại hình captcha khác (nghĩa là làm lại từ đầu)
                      $captcha->setTimeout('300')
                               ->setWordLen('6')
                               ->setHeight('70')
                               ->setWidth('150')
                               ->setFontsize('30')
                               ->setImgDir(APPLICATION_PATH.'/../public/default/captcha/images/')
                               ->setImgUrl(HOST_PATH.'/public/default/captcha/images/')
                               ->setFont('./public/default/captcha/font/arial.ttf');
                       $captcha->generate();
                       $this->view->imageCaptcha = $captcha->render();
                       $this->view->idCaptcha = $captcha->getId();
                       $sessionCaptcha = new Zend_Session_Namespace('Zend_Form_Captcha_'.$captcha->getId());
                       $sessionCaptcha->word = $captcha->getWord();
                       $this->view->message = "You Fail";
                    }
         }
}

Bước 2: Trong View của captchaAction()
<?php
if( $this->message != 'You Passed' )
 {
echo $this->imageCaptcha;
?>
<br/>
<form name="formcaptcha" method="post" action="">
  <p>
    <label>Captcha
      <input type="text" name="maCaptcha" id="maCaptcha">
    </label>
  </p>
  <br/>
  <p>
    <label>
      <input type="submit" name="checkcaptcha" id="checkcaptcha" value="CheckCaptcha">
    </label>
  </p>
  <input type="hidden" name="idCaptcha" value="<?php echo $this->idCaptcha ?>" >
</form>
<br/>
<?php echo $this->message; ?>
<?php }else{ 
            echo $this->message; 
           }?>

Bước 3: Tạo các thư mục như trong đường dẫn ở bước 1 chỗ setImgDir hay setImgUrl

Bước 4; Tạo thư mục font như trong đường dẫn ở bước 1 chỗ setFont và copy file arial.ttf vào thư mục đó. 

III. Kết hợp Zend Captcha với Form

Bước 1: Tạo một form Signup đơn giản chỉ có captcha và nút submit
Vào thư mục forms tạo một file signup.php với nội dung
<?php
class Default_Form_Signup extends Zend_Form
 {
  public function init()
   {
    // Captcha
    $captcha = new Zend_Form_Element_Captcha('captcha',array(
                              'label'=>'Captcha',
                              'captcha'=>array(
                                      'captcha'=>'Image',
                                       'timeout'=>'300',
                                       'wordLen'=>'6',
                                       'height'=>'70',
                                       'width'=>'150',
                                       'fontSize'=>'30',
                                       'imgDir'=>APPLICATION_PATH.'/../public/default/captcha/images/',
                                       'imgUrl'=>HOST_PATH.'/public/default/captcha/images/',
                                       'font'=>APPLICATION_PATH.'/../public/default/captcha/font/arial.ttf',
                                         ),
                              ));
    $this->addElement($captcha);
    // End Captcha
    
    //Submit
    $this->addElement('submit','checkcaptcha',array('label'=>'CheckCaptcha'));
    
   }
 }

Bước 2: Tạo các thư mục như cấu trúc chỗ imgDir ở bước 1 và thư mục font (nhớ copy font arial.ttf vào thư mục font )

Bước 3: Trong Controller tạo captchaformAction() với nội dung
public function captchaformAction()
  {
     $formSignup = new Default_Form_Signup(array('name'=>'formSignup','id'=>'formSignup','action'=>"",'method'=>'post'));  
     if( $this->_request->getPost('checkcaptcha') )
       {
          $captcha = $this->_request->getPost('captcha');
    
          $val_captcha = new Default_Form_Validate_Captcha();
          if( $val_captcha->isValid($captcha) )
           {
              echo "You Passed";   
           }else{
                   echo "You Fail";
                }
          
      }
      $this->view->formSignup=$formSignup;
  }

Bước 4: Tạo file để validate captcha
Vào thư mục forms tạo thư mục validate, trong thư mục validate tạo một file captcha.php với nội dung
<?php
class Default_Form_Validate_Captcha
 {
    static function isValid($captcha)
     {
        // lấy mã xác nhận do người dùng đánh
        $captchaWordInput = $captcha['input'];
        // Tạo Session Captcha
        $sessionCaptcha = new Zend_Session_Namespace('Zend_Form_Captcha_'.$captcha['id']);
        $sessionWord = $sessionCaptcha->getIterator();
        // Kiểm tra mã xác nhận
        if( isset($sessionWord['word']) && $captchaWordInput!="" && $sessionWord['word'] == $captchaWordInput )
         {
            return true; 
          }else{
                 return false;
               }
        
     }
 }

Tới đây chúng ta đã nắm được một số ít kiến thức về sử dụng Captcha trong Zend Framework.

Để có thể xóa các hình captcha ta sử dụng
 $mask = APPLICATION_PATH."/../public/default/captcha/images/*.png";
 array_map("unlink",glob($mask));
Ta nên xóa trong phần quản trị.
Nguồn: Sưu tầm Internet

1 nhận xét: