Zend Framework 2 – Sử dụng Authentication

ZF2 - AuthenticationTrong bài viết này, ta sẽ cùng tìm hiểu về Authentication (xác thực người dùng) trong Zend Framework 2. Qua đó bạn sẽ hiểu được cấu trúc của API và cách áp dụng vào dự án cụ thể.

Authentication Adapter

Nằm trong namespace Zend\Authentication, các lớp adapter bạn sử dụng cho tính năng này phải được hiện thực Zend\Authentication\Adapter\AdapterInterface. Interface này chỉ khai báo một phương thức duy nhất authenticate() có kiểu trả về là Zend\Authentication\Result. Các đối tượng adapter được tạo ra sẽ không được dùng trực tiếp mà sẽ thông qua một đối tượng service dùng để quản lý.
Zend Framework 2 cung cấp sẵn cho bạn một số kiểu adapter là: DbTable, Digest, HttpLdap.
– Digest:
Lớp Zend\Authentication\Result này định nghĩa một số hằng để xác định kết quả của việc xác thực.

class Result
{
	const FAILURE                        =  0;
	/**
	 * Failure due to identity not being found.
	 */
	const FAILURE_IDENTITY_NOT_FOUND     = -1;

	/**
	 * Failure due to identity being ambiguous.
	 */
	const FAILURE_IDENTITY_AMBIGUOUS     = -2;

	/**
	 * Failure due to invalid credential being supplied.
	 */
	const FAILURE_CREDENTIAL_INVALID     = -3;

	/**
	 * Failure due to uncategorized reasons.
	 */
	const FAILURE_UNCATEGORIZED          = -4;

	/**
	 * Authentication success.
	 */
	const SUCCESS                        =  1;

	// ...
}

Thông qua một đối tượng của kiểu Result này, bạn sẽ xác định được 3 thông tin từ quá trình authentication. Đó là:
– code: chứa giá trị của một trong các hằng trên.
– identity: là một đối tượng (có kiểu bất kì) chứa thông tin định danh người dùng
– messages: mảng chứa các thông điệp để báo cho người dùng biết nguyên nhân xác thực thất bại.

AuthenticationService và StorageInterface

Các đối tượng được tạo ra từ AdapterInterface (gián tiếp thông qua một lớp nào đó) thường không được dùng trực tiếp mà phải thông qua một đối tượng có kiểu AuthenticationService. AuthenticationService cung cấp các phương thức cần thiết để lưu trữ, kiểm tra, lấy các thông tin có được từ việc authentication.
Định nghĩa của lớp này có dạng sau:

<?php
namespace Zend\Authentication;

class AuthenticationService
{
    /**
	 *
     * @var Adapter\AdapterInterface|null
     */
    public function get/setAdapter();

    /**
     *
     * @var Storage\StorageInterface
     */
    public function get/setStorage();

    /**
     * Authenticates against the supplied adapter
     *
     * @param  Adapter\AdapterInterface $adapter
     * @return Result
     * @throws Exception\RuntimeException
     */
    public function authenticate(Adapter\AdapterInterface $adapter = null);

    /**
     * Returns true if and only if an identity is available from storage
     *
     * @return boolean
     */
    public function hasIdentity();

    /**
     * Returns the identity from storage or null if no identity is available
     *
     * @return mixed|null
     */
    public function getIdentity();

    /**
     * Clears the identity from persistent storage
     *
     * @return void
     */
    public function clearIdentity();
}

Khi gọi phương thức AuthenticationService::authenticate(), AuthenticationService sẽ lưu lại giá trị của Result::Identity vào một đối tượng có kiểu StorageInterface.
StorageInterface chỉ là một interface chứa các phương thức đơn giản như read(), write() dùng để chứa dữ liệu tại session (Zend\Authentication\Storage\Session) hoặc biến tạm (Zend\Authentication\Storage\NonPersistent). Mặc định AuthenticationService sẽ sử dụng session để lưu identity.

Để dễ nhớ, tôi đã  vẽ lại mô hình các lớp này bên dưới.

Zend Framework 2 - Authentication - Class Diagram

Ví dụ đơn giản

Trong phần này tôi sẽ tạo một lớp adapter mới với nhiệm vụ thực hiện đăng nhập bằng cách gọi một stored procedure. Stored procedure này sẽ trả về hai tham số output là errcode, errmsg để xác định lỗi trong trường hợp đăng nhập thất bại.

DELIMITER $$

DROP PROCEDURE IF EXISTS ocs_users_login$$

CREATE PROCEDURE ocs_users_login(
	IN i_username VARCHAR(255),
	IN i_password VARCHAR(255),
	OUT o_errcode INT,
	OUT o_errmsg NVARCHAR(255),
	OUT o_userid INT,
	OUT o_fullname VARCHAR(100))
BEGIN

	/*
		YOUR CODE HERE
	*/

END$$
DELIMITER ;

Lớp AuthAdapter với phương authenticate() đơn giản chỉ trả về một trong hai kết quả Result::SUCCESS và Result::FAILURE. Trong trường hợp cần chính xác, bạn phải gán lại giá trị này dựa vào tham số errcode trả ra từ stored procedure:

<?php
namespace AAC\Authentication;

use stdClass;
use Zend\Authentication\Adapter\AdapterInterface;
use Zend\Authentication\Result as AuthenticationResult;

class AuthAdapter implements AdapterInterface
{
	/**
     * Database Connection
     *
     * @var DbAdapter
     */
	protected $db = null;

	protected $username;
	protected $password;

    public function __construct($db, $username, $password)
    {
    	$this->db = $db;
        $this->username = $username;
        $this->password = $password;
    }

    /**
     * Performs an authentication attempt
     *
     * @return \Zend\Authentication\Result
     */
    public function authenticate()
    {

		$result = $this->login($this->username,$this->password);
    	if ($result["@errcode"]===NULL)
    	{
    		$identity = new stdClass();
    		$identity->userid = $result["@userid"];
    		$identity->fullname = $result["@fullname"];

    		return new AuthenticationResult(
    		 	AuthenticationResult::SUCCESS,
    		 	$identity,
    		 	array()
			);
    	}else {

    		return new AuthenticationResult(
    		 	AuthenticationResult::FAILURE,
    		 	null,
    		 	array($result["@errmsg"])
    		);
    	}
    }
    function login($username, $password)
	{
		$password = md5($password);

		$this->db->query("CALL uac_users_login(?,?,@errcode,@errmsg,@userid,@fullname)", array($username, $password));
		$result = $this->db->query("select @errcode, @errmsg, @userid,@userid,@fullname");
		$result = $result->execute()->current();
		return $result;
	}
}

Sử dụng AuthenticationService:

$sm = $this->getServiceLocator();
$dbAdapter = $sm->get('uacdb');

$auth = new AuthAdapter($dbAdapter,$username,$password);

$authService = new AuthenticationService(null,$auth);

$result = $authService->authenticate();

Sau đó bạn có thể dùng:

$authService->hasIdentity();

để kiểm tra người dùng đã đăng nhập chưa. Khi người dùng logout, bạn hãy gọi:

$authService->clearIdentity();

YinYangIt

Advertisements

One thought on “Zend Framework 2 – Sử dụng Authentication

  1. Pingback: zf2 authentication | nguyendanglinh Nguyễn đăng linh

Trả lời

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Đăng xuất / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Đăng xuất / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Đăng xuất / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Đăng xuất / Thay đổi )

Connecting to %s