Khanh Hoang - Kenn
Kenn is a user experience designer and front end developer who enjoys creating beautiful and usable web and mobile experiences.
- Đối bất kì ứng dụng web nào hiện nay để đảm bảo tính an toàn cho việc input dữ liệu và chống lại các Auto Post thì captcha là 1 phần không thể thiếu . Trong bài viết này tôi sẽ hướng dẫn các bạn các tạo Component Captcha và kết hợp với bài viết ứng dụng đăng nhập . (Xem tại đây)
- Các tạo Component Captcha tham khảo tại đây
- Code tham khảo đã được chỉnh sửa phù hợp với CakePHP version 1.3.6
- Xem bài lại bài viết ứng dụng đăng nhập
- Download PhpCaptcha tại http://www.ejeliot.com/pages/2 và giải nén cho vào thư mục /vendors/phpcaptcha (Tự tạo thêm thư mục phpcaptcha) . Sau khi giải nén ta có /vendors/phpcaptcha/php-captcha.php.
- Download Vera font tại http://ftp.gnome.org/pub/GNOME/sourc...-vera-1.10.zip và giải nén vào /vendors/phpcaptcha/fonts/ (Thư mục fonts tự tạo thêm)
- Lưu ý là bài biết này dựa trên bài viết ứng dụng đăng nhập nên các bạn phải xem lại bài trước.
Vào app/controllers/components tạo file Captcha.php :
<?php App::import('Vendor', 'phpcaptcha/php-captcha'); class CaptchaComponent extends Object { var $controller; //called before Controller::beforeFilter() function initialize(&$controller, $settings = array()) { // saving the controller reference for later use $this->controller =& $controller; } //called after Controller::beforeRender() function beforeRender(&$controller) { } //called after Controller::render() function shutdown(&$controller) { } //called before Controller::redirect() function beforeRedirect(&$controller, $url, $status=null, $exit=true) { } function redirectSomewhere($value) { // utilizing a controller method } function startup( &$controller ) { $this->controller = &$controller; } function image(){ $imagesPath = realpath(VENDORS . 'phpcaptcha').'/fonts/'; $aFonts = array( $imagesPath.'VeraBd.ttf', $imagesPath.'VeraIt.ttf', $imagesPath.'Vera.ttf' ); $oVisualCaptcha = new PhpCaptcha($aFonts, 500, 60); $oVisualCaptcha->UseColour(true); //$oVisualCaptcha->SetOwnerText('Source: '.FULL_BASE_URL); $oVisualCaptcha->SetNumChars(6); $oVisualCaptcha->Create(); } function audio(){ $oAudioCaptcha = new AudioPhpCaptcha('/usr/bin/flite', '/tmp/'); $oAudioCaptcha->Create(); } function check($userCode, $caseInsensitive = true){ if ($caseInsensitive) { $userCode = strtoupper($userCode); } if (!empty($_SESSION[CAPTCHA_SESSION_ID]) && $userCode == $_SESSION[CAPTCHA_SESSION_ID]) { // clear to prevent re-use unset($_SESSION[CAPTCHA_SESSION_ID]); return true; } else return false; } }
Trong Controller User (app/controllers/users_controller.php) :
Phần biến Components sẽ thêm Captcha vào
var $components = array("Session","Captcha");
Hàm login() cập nhật lại , kiểm tra Captcha trước rồi mới kiểm tra username và password :
//--------- Login function login(){ $error="";// thong bao loi if($this->Session->read($this->_sessionUsername)) $this->redirect("view"); if(isset($_POST['ok'])){ $username = $_POST['username']; $password = $_POST['password']; $captcha = $_POST['captcha']; if(!$this->Captcha->check($captcha)){ $error = "Captcha is wrong"; }else{ if($this->User->checkLogin($username,$password)){ $this->Session->write($this->_sessionUsername,$username); $this->redirect("view"); }else{ $error = "Username or Password is wrong"; } } } $this->set("error",$error); $this->render("/demos/users/login"); }
Vậy Controller User đầy đủ là :
<?php class UsersController extends AppController{ var $layout = false; // Khong su dung layout va su dung CSS rieng var $name = "Users"; var $helpers = array("Html"); // Su dung helper Html var $components = array("Session","Captcha"); // Su dung component Session var $_sessionUsername = "Username"; // ten cua Session //Create Captcha Image function captcha_image() { $this->Captcha->image(); } //---------- View function view(){ if(!$this->Session->read($this->_sessionUsername)) $this->redirect("login"); else $this->render("/demos/users/index"); } //--------- Login function login(){ $error="";// thong bao loi if($this->Session->read($this->_sessionUsername)) $this->redirect("view"); if(isset($_POST['ok'])){ $username = $_POST['username']; $password = $_POST['password']; $captcha = $_POST['captcha']; if(!$this->Captcha->check($captcha)){ $error = "Captcha is wrong"; }else{ if($this->User->checkLogin($username,$password)){ $this->Session->write($this->_sessionUsername,$username); $this->redirect("view"); }else{ $error = "Username or Password is wrong"; } } } $this->set("error",$error); $this->render("/demos/users/login_captcha"); } //---------- Logout function logout(){ $this->Session->delete($this->_sessionUsername); $this->redirect("login"); } }
Model giữ nguyên không có gì thay đổi .
File view login.cpt sẽ cập nhật lại như sau :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <?php echo $this->Html->css("login");?> <title>Login</title> <body> <form method="post" action=""> <fieldset> <legend>Login</legend> <label>Username</label><input type="text" name="username" size="20" /><br /> <label>Password</label><input type="password" name="password" size="20" /><br /> <img id="captcha" src="<?php echo $this->Html->url('/users/captcha_image/');?>" alt="" /><br /> <label>Captcha</label><input type="text" name="captcha" size="20" /><br /> <a href="javascript:void(0);" onclick="javascript:document.images.captcha.src='<?php echo $this->Html->url('/users/captcha_image/');?>?' + Math.round(Math.random(0)*1000)+1">Reload image</a><br /> <label> </label><input type="submit" name="ok" value="Login" /><br /> <span class="error"><?php echo $error; // hien thi thong bao loi neu co?></span> </fieldset> </form> </body> </html>
Khi truy cập vào http://localhost/cakephp/users/view nó sẽ chuyển sang trang này :
Nếu đăng nhập thành công :
- Nếu các bạn muốn customize fonts chữ , kích thướt chữ , kích thướt khung chứa ảnh captcha ...
Cách 1 : tao vào app/controllers/components/Captcha.php tìm function image()
function image(){ $imagesPath = realpath(VENDORS . 'phpcaptcha').'/fonts/'; $aFonts = array( $imagesPath.'VeraBd.ttf', $imagesPath.'VeraIt.ttf', $imagesPath.'Vera.ttf' ); $oVisualCaptcha = new PhpCaptcha($aFonts, 300, 30); $oVisualCaptcha->UseColour(true); //$oVisualCaptcha->SetOwnerText('Source: '.FULL_BASE_URL); $oVisualCaptcha->SetNumChars(5); $oVisualCaptcha->Create(); }
Chỉnh sửa trong function này .
Cách 2 :
Vào vendors/phpcaptcha/php-captcha.php Chỉnh sửa các hằng số sau :
define('CAPTCHA_SESSION_ID', 'php_captcha'); define('CAPTCHA_WIDTH', 200); // max 500 define('CAPTCHA_HEIGHT', 50); // max 200 define('CAPTCHA_NUM_CHARS', 5); define('CAPTCHA_NUM_LINES', 70); define('CAPTCHA_CHAR_SHADOW', false); define('CAPTCHA_OWNER_TEXT', ''); define('CAPTCHA_CHAR_SET', ''); // defaults to A-Z define('CAPTCHA_CASE_INSENSITIVE', true); define('CAPTCHA_BACKGROUND_IMAGES', ''); define('CAPTCHA_MIN_FONT_SIZE', 16); define('CAPTCHA_MAX_FONT_SIZE', 25); define('CAPTCHA_USE_COLOUR', false); define('CAPTCHA_FILE_TYPE', 'jpeg'); define('CAPTCHA_FLITE_PATH', '/usr/bin/flite'); define('CAPTCHA_AUDIO_PATH', '/tmp/'); // must be writeable by PHP process
Cách 3 : Cách này linh họa hơn , bạn có thể viết thêm các hàm xử lý tham số vào Component Captcha , để khi trong Controller gọi và gán giá trị sẽ rất linh hoạt.