📜 ⬆️ ⬇️

Workshop Zend Framework. Part One: Authentication and Acl


Recently, I am becoming 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 a site framework on the Zend Framework, which will provide the necessary framework for the implementation of sites of average complexity :

Authentication


Authentication is an integral part of almost any site. As you know, the Zend Framework uses a special component, Zend_Auth, for this purpose. This component allows you to perform the login process by checking the match of the login-password pair. Typically, the entry point is a special action authentication, as well as a possible action registration (or registration confirmation). Consider a simple authentication example:
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); //       storage    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. To complete the work you will need the appropriate form, which sends the username and password to this action.
After successful authentication, user data is stored in the Zend_Auth storage. Further, when you need to find out any information about the current user, you can refer to Zend_Auth (it is available everywhere, because it is a implementation of Singleton) as follows:
 $auth = Zend_Auth::getInstance(); //    if ($auth->hasIdentity()){ //     $user_data = $auth->getStorage()->read(); } 

Also an important action to be taken is the initial initialization of Zend_Auth when the user first visits the site. To do this, add the following method to the bootstrap:
 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); } } 

Acl


Most web applications have several access statuses, each of which has certain privileges. For most sites, the privileges and their distribution are relatively constant, so we implement Acl in the form of rules written directly in the program code. If you are developing a system that has a frequently changing structure of statuses and rights (for example, CMS), then you need to build a more flexible implementation of Acl, the rights in which will be stored, for example, in a database.
The main tasks to be performed by the access control system are the assignment of privileges and access control itself. To accomplish these tasks, we need two components:
Consider the simplest case when resources are parts of the site, i.e. in MVC terms, actions. Each user inherits rights from a certain abstract status (guest, user, administrator), the privileges of each status are described in Acl. To implement Acl, expand Zend_Acl:
 class Acl extends Zend_Acl { public function __construct() { //  $this->addRole('guest'); $this->addRole('user', 'guest'); $this->addRole('admin', 'user'); //  //   ! $this->add(new Zend_Acl_Resource('guest_allow')); $this->add(new Zend_Acl_Resource('index/index'),'guest_allow'); //... //   ! $this->add(new Zend_Acl_Resource('user_allow')); $this->add(new Zend_Acl_Resource('user/index'), 'user_allow'); // ... //   ! $this->add(new Zend_Acl_Resource('admin_allow')); $this->add(new Zend_Acl_Resource('admin/index'), 'admin_allow'); //... // , -   $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'){ //  $request = Zend_Controller_Front::getInstance()->getRequest(); $resource = $request->getControllerName() . '/' . $request->getActionName(); //      if (!$this->has($resource)) return true; //  $storage_data = Zend_Auth::getInstance()->getStorage()->read(); $role = array_key_exists('status', $storage_data)?$storage_data->status : 'guest'; return $this->isAllowed($role, $resource, $privilege); } } 

Put this code in the file application / classes / Acl.php.
We describe the lists of rights in the standard form for ZF. A method is also created here that checks the current user's access rights to the current action. As resource identifiers, the controller / action format is used. If you design the system in such a way that you do not change permissions inside the controller, then you can use only the names of controllers instead of resource identifiers (do not forget to change the can method).
For more flexibility, we add the concept of "privilege", which allows you to control certain actions within the action. The privilege to view is called "show."
Now, when we have a list of access rights and we are able to determine whether a user has access to the current action, we need to embed the check into the Zend Framework request processing cycle. Creating a front controller plugin is best suited for this. Plugins allow you to perform specified actions at various stages of the dispatching process:
 class CheckAccess extends Zend_Controller_Plugin_Abstract { /** *  preDispatch      *  controller/action      * 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(); } } /** *       . *     error     *      . * * @param string $msg */ public function generateAccessError($msg=' !'){ $request = $this->getRequest(); $request->setControllerName ('error'); $request->setActionName('error'); $request->setParam('message', $msg); } } 

Place this code in the file application / plugins / CheckAccess.php.
This plugin will perform user access checks on each request coming to the site. To test access, use the Acl class, discussed above. In case of an error, the request will be focused on error / error. In order to correctly display an error message, you need to add the corresponding code in ErrorController.php.
Now you need to connect the plugin and create an Acl resource in bootstrap:
 public function _initAcl(){ Zend_Loader::loadClass('Acl'); Zend_Loader::loadClass('CheckAccess'); Zend_Controller_Front::getInstance()->registerPlugin(new CheckAccess()); return new Acl(); } 

In order for Zend_Loader to “know” where to look for our files, add it to application.ini:
includePaths.plugins = APPLICATION_PATH "/ plugins"
includePaths.classes = APPLICATION_PATH "/ classes"

PS This post only considers one of the ways to implement access control, which is not universal, but meets the needs of most small sites.

')

Source: https://habr.com/ru/post/121114/


All Articles