Workshop Zend Framework. Part one: Authentication and Acl

Lately I'm more and more convinced of the universality of the Zend Framework as a platform for creating web applications. Today I will talk about the process of creating the skeleton of the website in Zend Framework which will provide the necessary basis for the realization of sites of medium complexity:
the
- Part two
theRouting — customize URLs for various system components
Part one
the
Authentication — users log on to the system
ACL — distribution of access rights
the
Registry — quick access to system constants
Authentication
Authentication is an integral part of almost any website. As you know, for these purposes, the Zend Framework uses a special component of Zend_Auth. This component allows the login process to the system by matching login and password. Usually the entry point is a special action of authentication and possible action registration (or registration confirmation). Consider a simple example of authentication:
the
public function authAction(){
$form = new Application_Form_Enter();
if ($form->isValid($this->getRequest()->getPost())){
$bootstrap = $this- > getInvokeArg('bootstrap');
$auth = Zend_Auth::getInstance();
$adapter = $bootstrap- > getPluginResource('db')->getDbAdapter();
$authAdapter = new Zend_Auth_Adapter_DbTable(
$adapter, 'user', 'login',
'password', 'MD5(?)'
);
$authAdapter- > setIdentity($form->login->getValue());
$authAdapter- > setCredential($form->password->getValue());
$result = $auth->authenticate($authAdapter);
// If the validation is successful, stored in the storage info about the user
if ($result->isValid()){
$storage = $auth- > getStorage();
$storage_data = $authAdapter- > getResultRowObject(
null,
array('activate', 'password', 'enabled'));
$user_model = new Application_Model_DbTable_User();
$language_model = new Application_Model_DbTable_Language();
$storage_data- > status = 'user';
$storage- > write($storage_data);
}
}
}
This is a typical authentication code that you can use. For this you need appropriate form, which sends username and password for this action.
After successful authentication the user information is stored in the repository (storage) Zend_Auth. Further, when you'll need to know some information about the current user, you can turn to Zend_Auth (it is available everywhere, because it is a Singleton implementation) in the following way:
the
$auth = Zend_Auth::getInstance();
// If the user is authenticated
if ($auth- > hasIdentity()){
// We read the data about the user
$user_data = $auth->getStorage()->read();
}
Also an important action to take is the initialization Zend_Auth when the first user logs on the website. This will add bootstrap in the following method:
the
public function _initAuth(){
$auth = Zend_Auth::getInstance();
$data = $auth->getStorage()->read();
if (!isset($data->status)){
$storage_data = new stdClass();
$storage_data- > status = 'guest';
$auth->getStorage()->write($storage_data);
}
}
the
Acl
In most web applications, there are several statuses of access, each of which has certain privileges. For most sites, benefits and their distribution are relatively constant, so we implement the Acl in the form of rules written directly in program code. If you are developing a system that is often changing the structure of statuses and rights (e.g. CMS), then you need to build a more flexible Acl implementation, the rights in which are stored, for example, in the database.
The main tasks to be performed by the access control system is the assignment of privileges and the access control. To implement these tasks, we need two components:
-
the
- Acl — access control lists the
- Plugin checks the correctness of the access of the current user to the requested resource Let's consider the simple case where resources are part of the site, i.e. in terms of the MVC action. Each user inherits the rights from a certain abstract status (guest, user, administrator) privileges of each status are described in Acl. To implement Acl extend Zend_Acl:
the
class Acl extends Zend_Acl {
public function __construct() {
//Add role
$this->addRole('guest');
$this->addRole('user', 'guest');
$this->addRole('admin', 'user');
//Add resources
// RESOURCES GUEST !
$this->add(new Zend_Acl_Resource('guest_allow'));
$this->add(new Zend_Acl_Resource('index/index'),'guest_allow');
//...
// THE USER'S RESOURCES !
$this->add(new Zend_Acl_Resource('user_allow'));
$this->add(new Zend_Acl_Resource('user/index'), 'user_allow');
// ...
// RESOURCES ADMIN !
$this->add(new Zend_Acl_Resource('admin_allow'));
$this->add(new Zend_Acl_Resource('admin/index'), 'admin_allow');
//...
//Put rights, default all is forbidden
$this- > deny(null, null, null);
$this->allow('guest', 'guest_allow', 'show');
$this->allow('user', 'user_allow', 'show');
$this->allow('admin','admin_allow', 'show');
}
public function can($privilege='show'){
//Initiate the resource
$request = Zend_Controller_Front::getInstance()->getRequest();
$resource = $request- > getControllerName() . '/' . $request->getActionName();
//If the resource is not found close the access
if (!$this->has($resource))
return true;
//Initiating role
$storage_data = Zend_Auth::getInstance()->getStorage()->read();
$role = array_key_exists('status', $storage_data)?$storage_data- > status : 'guest';
return $this- > allowed($role, $resource, $privilege);
}
}
Put this code in the file application/classes/Acl.php.
Lists the rights described in standard ZF form. Also here is created a method that checks access rights of the current user to the current action. As identifiers of resources used by the format controller/action. If you design the system so that you have the right of action inside the controller do not change, you can use resource IDs instead of only the names of the controllers (don't forget to change the method
can
).For more flexibility we add the concept of "privilege", which allows you to control certain actions within an action. The privilege to view has the name "show".
Now that we have a list of access rights and we are able to determine whether the user has access to the current action, we need to introduce the test into a cycle of query processing by the Zend Framework. This is best suited to create a front controller plugin. Plugins allow you to perform specified actions on different stages of the process dispatching:
the
class CheckAccess extends Zend_Controller_Plugin_Abstract {
/**
* PreDispatch method checks access rights
* this controller/action in case of error, calls a method
* generateAccessError
*
* @param Zend_Controller_Request_Abstract $request
*/
public function preDispatch(Zend_Controller_Request_Abstract $request) {
$acl = Zend_Controller_Front::getInstance()->getParam('bootstrap')- > getResource('Acl');
if (!$acl- > can()){
$this->generateAccessError();
}
}
/**
* Method generating the error message to the access rights.
* Performs a redirect to the error controller and displays it
* the error message passed to the method.
*
* @param string $msg
*/
public function generateAccessError($msg='Access denied!'){
$request = $this->getRequest();
$request- > setControllerName ('error');
$request- > setActionName('error');
$request->setParam('message', $msg);
}
}
Put this code in the file application/plugins/CheckAccess.php.
This plugin will check the user's access each request coming to the site. For the access check uses the class of the Acl discussed above. In case of an error the query will be targeted at error/error. In order to correctly output an error message, you need to add the appropriate code in ErrorController.php.
Now you need to connect the plugin and create a resource Acl in bootstrap:
the
public function _initAcl(){
Zend_Loader::loadClass('Acl');
Zend_Loader::loadClass('CheckAccess');
Zend_Controller_Front::getInstance()->registerPlugin(new CheckAccess());
return new Acl();
}
To Zend_Loader "knew" where to find our files we will add in application.ini:
includePaths.plugins = APPLICATION_PATH "/plugins"
includePaths.classes = APPLICATION_PATH "/classes"
P. S. this post discusses just one way of implementing access control, which is not generic, but meets the needs of the majority of the sites
Комментарии
Отправить комментарий