Trang

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

Refresh Captcha trong Zend Framework [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

Phần lý thuyết các bạn xem Zend_Captcha

II. Viết ứng dụng đăng kí  thành viên

Bước 1: Vào thư mục public/default tạo một thư mục mới tên là captcha

Bước 2: Trong thư mục captcha vừa tạo, tạo thêm 2 thư mục là imagesfont

Bước 3: Copy file arial.ttf vào thư mục font

Bước 4: Tạo form đăng kí thành viên
Trong thư mục forms tạo file signup.php với nội dung
<?php
class Default_Form_Signup extends Zend_Form
 {
  public function init()
   {
    //Username
         $this->addElement('text','username',array(
                                                'label'=>'Username',
                                                'size'=>21,
                                                ));
         $username = $this->getElement('username');
         //Validate
         //NotEmpty
         $username->setRequired(true)
               ->addValidator('NotEmpty',true)
                ->getValidator('NotEmpty')->setMessage('Username không được bỏ trống.');
         //Không có dấu, khoảng trắng và các kí tự đặc biệt
         $username->addValidator('Regex',true,array('/^[a-zA-Z0-9]*$/'))
               ->getValidator('Regex')->setMessage('Username không hợp lệ.');
         //Filter
         $username->addFilter('Stringtrim')
               ->addFilter('StringToLower');
    //End Username
         
    //Password
         $this->addElement('password','password',array(
                                                       'label'=>'Password',
                                                       'size'=>21
                                                       ));
         $password=$this->getElement('password');
         //Validate
         //NotEmpty
         $password->setRequired(true)
                  ->addValidator('NotEmpty')
                  ->getValidator('NotEmpty')->setMessage('Password không được bỏ trống');
         //Không có dấu, khoảng trắng và các kí tự đặc biệt
         $password->addValidator('Regex',true,array('/^[a-zA-Z0-9]*$/'))
                  ->getValidator('Regex')->setMessage('Password không hợp lệ.');
        //Filter
        $password->addFilter('StringTrim')
                 ->addFilter('StringToLower');
    //End password
    
    // Captcha
    $this->addElement('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',
                                       'messages'=>array(
                                                         'badCaptcha'=>'Mã xác nhận không chính xác',
                                                         
                                                         ),
                                         ),
                              ));
  // End Captcha
    
  // Refresh captcha
    $this->addElement('hidden','refreshcaptcha',array( 
                                               'required'=>false,
                                               'ignore'=>true,
                                               'autoInsertNotEmptyValidator'=>false,
                                               'decorators'=>array(
                                                                   array('HtmlTag',
                                                                         array('tag'=>'div',
                                                                                'id'=>'imgRefreshCaptcha',
                                                                                'title'=>'Refresh Captcha',
                                                                                
                                                                               )
                                                                         ),
                                                                  ),
                                               
                                               ));
    $refreshcaptcha = $this->getElement('refreshcaptcha')
                          ->clearValidators();
   // End Refresh captcha

  //Submit
    $this->addElement('submit','signup',array('label'=>'Signup'));
    
   }
 }

Bước 5: Tạo nút refreshcaptcha
Ở bước 4, trong file signup.php, ta có tạo một element là refreshcaptcha với id là imgRefreshCaptcha, ta tiến hành định dạng css cho nó với background là nút refresh.




Css:
#imgRefreshCaptcha{background-image:url(../images/icons/refresh.png);height:24px;width:24px;margin-left:5px;cursor:pointer}

Bước 6: Trong Controller tạo captchaformAction() với nội dung
public function captchaformAction()
 {
     // Tạo đối tượng FormSignup
     $formSignup = new Default_Form_Signup(array('name'=>'formSignup','id'=>'formSignup','action'=>"",'method'=>'post'));
     // Submit
     if( $this->_request->getPost('signup') )
       {
          // Xóa hình captcha
          $captchaImage = $this->_request->getPost('captcha');
          $delCaptchaImage = APPLICATION_PATH."/../public/default/captcha/images/".$captchaImage['id'].".png";
          array_map("unlink",glob($delCaptchaImage)); 
          //Validate formSignup
          if($formSignup->isValid($this->_request->getPost()))
           {
                // Lấy giá trị các tham số
                $arrayData=$formSignup->getValues();
                
                // Chú ý: Ta không cần phải Validate Captcha ở đây. Vì nó đã được kiểm tra chỗ formSignup->isValid
                // Để chắc chắn hơn thì Validate, không thì cũng không sao, chạy đỡ chậm hơn. 
                // Validate Captcha
                $val_captcha = new Default_Form_Validate_Captcha();
                if( $val_captcha->isValid($arrayData['captcha']) )
                 {
                    // Xử lý tiếp ở đây
                    echo "You Passed";
                 }
              //End Validate Captcha
             
           }//End Validate FormSignup
           
     }// End Submit
      $this->view->formSignup=$formSignup;
 }

Bước 7: Tạo View captchaform.phtml với nội dung
<?php
echo $this->formSignup;
?>
<script>
$(document).ready(function(){
  var count=1;
  $("#imgRefreshCaptcha").click(function(){
       if(count<6)
       {
       jQuery.ajax({
                  type:"POST",
                  url:"<?php echo HOST_PATH ?>/default/index/refreshcaptcha",
                  success:function(data){
                     $("#captcha-element").html(data);
                  },
                  error:function(){
                   alert('Có lỗi xảy ra. Xin thử lại sau');
                  },
        });//end Ajax
         count++;
        }else{
              alert('Có lỗi xảy ra. Xin thử lại sau');
              window.location.href="<?php echo HOST_PATH?>/default/index/index";
             }
  });
});
</script>

Phần này có xử lý Ajax tới refreshcaptchaAction() để khi ấn nút refresh thì sẽ chuyển hình captcha mới. Có hạn chế số lần ấn nút để hạn chế việc tạo hình captcha.

Bước 8: Trong Controller tạo refreshcaptchaAction() với nội dung
// Ajax refesh captcha    
public function refreshcaptchaAction()
 { 
      
      $modName = $this->_request->getModuleName();
      $conName = $this->_request->getControllerName();
      
      $urlMySite = HOST_PATH."/$modName/$conName/captchaform";
    
    // RefreshCaptcha
    /*
      1 - $this->_request->isXmlHttpRequest() là để kiểm tra xem có đúng là ajax request không,
          để tránh tình trạng chạy trực tiếp Action này, hoặc ai đó tạo 1 form rồi submit đến Action này
      2 - $_SERVER['HTTP_REFERER'] : khi mình đang ở trang abc.com, trong trang này có đường link
           đến trang 123.com, trong trang 123.com mình echo $_SERVER['HTTP_REFERER'], nếu mình click
           vào đường link đến 123.com thì kết quả hiện ra là abc.com. 
           Hay nói cách khác là địa chỉ của trang web mà từ đó user link đến trang này
 
          Mình sẽ so sánh link mà từ đó chạy ajax đến, nếu link đó giống với link urlMySite của mình thì ok, ngược lại
          thì disable View, tránh tình trạng Ajax từ 1 trang khác
    */
      if( $this->_request->isXmlHttpRequest() && $urlMySite == $_SERVER['HTTP_REFERER'] )
       {
          
          $refreshcaptcha = new Zend_Form_Element_Captcha('captcha',array(
                              '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',
                                       'messages'=>array(
                                                         'badCaptcha'=>'Mã xác nhận không chính xác',
                                                         
                                                         ),
                                         ),
                              ));
            // Xóa Label Captcha
            $refreshcaptcha->removeDecorator('label');
            
            // Truyen Captcha hinh
            $this->view->refreshcaptcha=$refreshcaptcha;
            
            // Disable Layout
            $this->_helper->layout->disableLayout();  
          
       }else{
              $this->getHelper('ViewRenderer')->setNoRender();
              }
                  
 }
// End Ajax refesh captcha        

Bước 9: Tạo View refreshcaptcha.phtml
<?php
echo $this->refreshcaptcha;
?>

Bước 10: 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;
               }
        
     }
 }

Kết quả:

Để 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

Không có nhận xét nào:

Đăng nhận xét