Để tiến tới xây dựng trang đăng nhập hệ thống ta sử dụng thư viện Zend_Auth trong ZF. Thư viện này đã hỗ trợ chúng ta trong việc thiết lập và sử dụng những chức năng cơ bản của quá trình chứng thực người dùng.
Để kích hoạt Zend_Auth ta cần thiết lập Zend_session tại file bootstrap.php chính: protected function _initSession(){
Zend_Session::start(); }
Tiếp tục, tại Model Muser. Ta lại thiết lập phương thức checklogin(). Công việc chính của phương thức này là sử dụng lớp Zend_Auth để chứng thực xem người dùng nhập thông tin username và password có đúng với CSDL hay không.
Trước hết, ta cần kiểm tra xem người dùng có nhập liệu hay không ?. Nếu có ta tiếp tục khởi tạo Zend_Registry. Công việc của thư viện này là chúng sẽ lấy thông tin kết nối CSDL tại phương thức _initDB() mà ta đã cấu hình tại bootstrap.php chính
function checklogin($data) {
if($data['username'] != NULL && $data['password'] != NULL) {
$registry = Zend_Registry::getInstance ();
$DB = Zend_Registry::get ( 'DB' ); }
}
Sau đó, ta lại khởi tạo đối tượng Zend_Auth với những tham số như biến kết nối, tên bảng, tên cột username, tên cột password. Tiếp theo là dòng màu vàng. Dòng này làm công việc thêm điều kiện là chỉ cho phép những ai có level là 2.
Kế tới ta truyền tham số username và password từ form nhập liệu của người dùng vào để so sánh với thông tin tại CSDL.
function checklogin($data) {
if($data['username'] != NULL && $data['password'] != NULL) {
$flag = false;
$registry = Zend_Registry::getInstance ();
$DB = Zend_Registry::get ( 'DB' );
$authAdapter = new Zend_Auth_Adapter_DbTable ( $DB, 'user', 'username', 'password');
$authAdapter->getDbSelect()->where("level = '2'");
$authAdapter->setIdentity ($data['username'] );
$authAdapter->setCredential ( $data['password'] );
$auth = Zend_Auth::getInstance ();
$result = $auth->authenticate ( $authAdapter ); }
}
Nếu quá trình kiểm tra hoàn tất và chúng hoàn toàn hợp lệ thì việc còn lại của chúng ta là đưa giá trị trong cột vào session. Dĩ nhiên với password thì chúng ta không nên đưa vào session (lưu ý là ta không cần thiết lập session vì bản thân zend_auth đã thay ta làm những việc này rồi).
function checklogin($data) {
if($data['username'] != NULL && $data['password'] != NULL) {
$flag = false;
$registry = Zend_Registry::getInstance ();
$DB = Zend_Registry::get ( 'DB' );
$authAdapter = new Zend_Auth_Adapter_DbTable ( $DB, 'user', 'username', 'password', ' level = 2' );
$authAdapter->setIdentity ($data['username'] );
$authAdapter->setCredential ( $data['password'] );
$auth = Zend_Auth::getInstance ();
if ($result->isValid ()) {
$data_sess = $authAdapter->getResultRowObject ( null, 'password' );
$auth->getStorage()->write($data_sess); return true; } else{ return false; } } }
Sau cùng, hàm checklogin này sẽ trả về giá trị là true hoặc false. Nếu kết quả chứng thực hoàn tất ta sẽ trả về true. Ngược lại sẽ là false.
Tại loginAction() ta sẽ thiết lập như sau: public function loginAction() {
$muser= new Admin_Model_DbTable_Muser(); if($this->_request->ispost())
{
$data=$this->_request->getParams(); if($muser->checklogin($data)== true) {
$this->_redirect("/admin/user/index"); }
else{
$err="Wrong username or password";
$this->view->error=$err; }
}} }
Nhiệm vụ của action này là sẽ load nội dung của Model Muser. Nếu người dùng có nhấn submit thì chúng ta sẽ lấy các tham số và đưa chúng vào biến $data. Cuối cùng ta gọi phương thức checklogin() để kiểm tra. Nếu chúng hợp lệ, ta đưa người dùng về trang hiển thị thông tin, ngược lại ta sẽ báo lỗi và trả kết quả về view.
Vậy tại Login.phtml (view) ta sẽ thiết lập như sau: <?php
if($this->error) {
echo $this->error; }
?> <p>
<form action="" method="post">
Username: <input type="text" name="username" size=25 /><br /> Password: <input type="password" name="password" size=25 /><br /> <input type="submit" name="ok" value="Login" />
</form> </p>
Kế tới, ta cần tạo sự khống chế khi người sử dụng truy cập. Có nghĩa là kiểm soát nếu người truy cập chưa đăng nhập thì sẽkhông thể truy cập vào các controller và action tại module admin.
Cách giải quyết tốt nhất là tại class chủ đạo: QHO_Controller_Action ta thêm đoạn code kiểm tra session. Nếu người dùng truy cập vào các controller và action khác mà chưa đăng nhập họ sẽ tự động được đẩy tới Action. Cụ thể sẽ như sau:
$data1=$this->_request->getParams();
$this->view->placeholder('Login')->login = false;
$auth = Zend_Auth::getInstance(); if($auth->getIdentity()){
$this->view->placeholder('Login')->login = true; }
else{
if($data1['controller'] != 'user' || $data1['action'] !='login'){
$this->_redirect('/admin/user/login/'); }
}
Quá trình trên được hiểu giản đơn như sau:
+ Đầu tiên ta lấy ra tất cả tham số từ phía người dùng (module nào, controller nào, action nào).
+ Kế tới ta sử dụng 1 biến placeholder tên là Login và gán chúng mặc định là false. + Khởi tạo đối tượng Zend_Auth.
+ Kiểm tra xem có tồn tại tham số session tại Zend_Auth hay không ?. + Nếu có sẽ gán biến placeholder là true.
+ Nếu không ta kiểm tra xem controller của họ đang truy cập liệu có khác user và action mà họ truy cập có khác login hay không. Nếu chúng khác ta sẽ đẩy họ tới trang login để thực thi việc đăng nhập vào hệ thống.
Như vậy, nếu code diễn tiến đúng ta sẽ có kết quả như sau:
Chú ý rằng, trong phần xử lý ở trên. Ta sử dụng biến placeholder tên là Login rất nhiều. Việc sử dụng biến này thực chất là chúng ta sử dụng để khống chế layout. Vì
nếu sử dụng như hình trên thì rõ ràng người chưa đăng nhập cũng có thể thấy cả menu, layout và những thông tin nhạy cảm trong trang admin. Vì thế ta cần dùng một biến placeholder để kiểm tra trong layout.
Lúc này ta sẽ có code triển khai như sau tại layout.phtml của module admin. <?php echo $this->doctype(); ?>
<head>
<?php echo $this->headMeta(); ?> <?php echo $this->headTitle(); ?> <?php echo $this->headLink()?> <?php echo $this->headScript()?> </head>
<body> <?php
if($this->placeholder('Login')->login == true) {
require("top.phtml"); require("left.phtml"); ?>
<div id=info>
<div class=main_info>
<?php echo $this->layout()->content; ?> </div> </div> <?php require("bottom.phtml"); } else {
echo $this->layout()->content; }
?> </body> </html>
Vậy nếu biến placeholder Login có giá trị là true (tức người dùng đã đăng nhập) ta sẽ gán layout hiển thị bao gôm top, left, bottom. Như mọi người vẫn thấy. Ngược lại, ta sẽ chỉ show ra duy nhất 1 form login mà thôi.
Nhưng, vấn đề mà chúng ta gặp phải là chẳng lẽ ở trang người dùng chúng ta cũng phải kiểm tra như thế ?. Vì nếu ta viết ở QHO_Controller_Action thì có nghĩa là nó sẽ được gọi cả ở module default và admin. Do đó, nó hoàn toàn không hề tối ưu nếu chúng ta triển khai chúng ở mọi module.
Lúc này, ta cần tách ra thêm 1 class thực hiện các nhiệm vụ được giao cho từng module tương ứng. Cụ thể là module admin ta sẽ có class riêng dành cho nó như: QHO_Controller_Admin, dĩ nhiên class này sẽ kế thừa từ nền tảng của class QHO_Controller_Action và chúng thừa hưởng các đặc tính mà Action vốn có.
Vậy tại library/QHO/Controller/ ta tạo thêm file admin.php với nội dung mà ta đề cập ở trên. Và nhớ rằng để kế thừa hàm init() của action.php ta cũng cần phải khai báo bằng từ khóa parent.
Vậy code tương đương sẽ như sau: <?php
class QHO_Controller_Admin extends QHO_Controller_Action{ public function init()
{
parent::init();
$data1=$this->_request->getParams();
$this->view->placeholder('Login')->login = false;
$auth = Zend_Auth::getInstance(); if($auth->getIdentity()){
$this->view->placeholder('Login')->login = true; }
else{
if($data1['controller'] != 'user' ||
$data1['action'] !='login') {
$this->_redirect('/admin/user/login/'); }
}} } }
Tiếp tục, tại file UserController.php và cả các Controller khác của Module Admin ta cũng cần chỉnh lại cho phù hợp như sau:
<?php
class Admin_UserController extends QHO_Controller_Admin {
Kế tới, ta thiết lập chức năng logout. Để làm được ta cũng cần có logoutAction() và phương thức logout() tại Model.
Tạo phương thức logout() tại Model: function logout(){
$auth = Zend_Auth::getInstance();
$auth->clearIdentity(); }
Tạo tiếp phương thức logoutAction() với nội dung: public function logoutAction()
$mem=new Admin_Model_DbTable_Muser;
$mem->logout();
$this->_redirect("/admin/user/login/");
$this->_helper->viewRenderer->setNoRender(true); }
Như vậy, thông qua mini app này các bạn đã ít nhiều hiểu được các kiến thức trong Zend Framework 1.x rồi phải không nào. Tiếp tục, tự các bạn hãy mở rộng và xây dựng hoàn chỉnh ứng dụng của mình nhé.
Mọi thắc mắc và góp ý xin gởi về email: kenny@qhonline.info
Khóa học Zend Framework 2.x tại QHOnline sẽ được ra mắt vào tháng 10/2014 với kiến thức nền tảng dựa theo PHP ở các phiên bản mới. Nếu các bạn quan tâm có thể truy cập vào website: www.qhonline.edu.vnđể cập nhật thông tin về khóa học trong tháng 10.