1

我正在 zf3 中开发专辑应用程序。我向应用程序添加了 acl 功能,如下所示:

专辑控制器.php

class AlbumController extends AbstractActionController
{
protected $role;
public function onDispatch(\Zend\Mvc\MvcEvent $e)
{
    $userSession = new Container('user');
    if (!isset($userSession->email)) {
        return $this->redirect()->toRoute('login');
    }
    else {
        $this->role = $userSession->role;
        parent::onDispatch($e);
      }
    }
public function checkPermission($role,$action)
{
  if($role == 'admin'){
    $acl = new Acl();
    if ($acl->isAllowed('admin', 'AlbumController', $action)) {
        return true;
    }
  }
  return false;
}
public function editAction()
{
  $action = 'edit';
  $permission = $this->checkPermission($this->role,$action);
  if (!$permission) {
      $this->flashMessenger()->addMessage('<div class="alert alert-  danger" role="alert"><b>You dont have the privilege to edit!!</b></div>');
      return $this->redirect()->toRoute('album');
  }
  $id = (int) $this->params()->fromRoute('id', 0);

    if (0 === $id) {
        return $this->redirect()->toRoute('album', ['action' => 'add']);
    }
    try {
        $album = $this->table->getAlbum($id);
    } catch (\Exception $e) {
        return $this->redirect()->toRoute('album', ['action' => 'index']);
    }

    $form = new AlbumForm();
    $form->bind($album);
    $form->get('submit')->setAttribute('value', 'Edit');

    $request = $this->getRequest();
    $viewData = ['id' => $id, 'form' => $form];
    if (! $request->isPost()) {
        return $viewData;
    }

    $form->setInputFilter($album->getInputFilter());
    $form->setData($request->getPost());
    $edit = $request->getPost('submit', 'Cancel');
    if($edit == 'Cancel'){
      $this->flashMessenger()->addMessage('<div class="alert alert-danger" role="alert"><b>Cancelled by User...!!</b></div>');
      return $this->redirect()->toRoute('album');
    }
    if (! $form->isValid()) {
        $this->flashMessenger()->addMessage('<div class="alert alert-danger" role="alert"><b>Failed to Update...!!</b></div>');
        return $viewData;
    }else{
      $this->table->saveAlbum($album);
      $this->flashMessenger()->addMessage('<div class="alert alert-success" role="alert"><b>Record Updated Successfully...!!</b></div>');
    }
    // Redirect to album list
    return $this->redirect()->toRoute('album', ['action' => 'index']);
}
}

这工作得很好,现在我想将 onDispatch 函数移动到 Module.php 但不知道如何实现它。有人可以帮我吗

模块.php

<?php
 namespace Album;

 use Album\Controller\AlbumController;
 use Album\Model\Album;
 use Album\Model\AlbumTable;
 use Zend\Db\Adapter\AdapterInterface;
 use Zend\Db\ResultSet\ResultSet;
 use Zend\Db\TableGateway\TableGateway;
 use Zend\ModuleManager\Feature\ConfigProviderInterface;
 use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
 use Album\Model\LoginTable;

 class Module implements ConfigProviderInterface
 {
  public function getConfig()
  {
     return include __DIR__ . '/../config/module.config.php';
  }

  public function getServiceConfig()
    {
    return [
        'factories' => [
            AlbumTable::class => function($container) {

                $tableGateway = $container->get(Model\AlbumTableGateway::class);
                return new AlbumTable($tableGateway);
            },
            Model\AlbumTableGateway::class => function ($container) {

                $dbAdapter = $container->get(AdapterInterface::class);

                $resultSetPrototype = new ResultSet();
                $resultSetPrototype->setArrayObjectPrototype(new Album());
                return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
            },
            Model\LoginTable::class =>  function($container) {
            $tableGateway = $container->get(Model\LoginTableGateway::class);
            $table = new LoginTable($tableGateway);
            return $table;
           },
                    Model\LoginTableGateway::class => function ($container){
                     $dbAdapter = $container->get(AdapterInterface::class);
                     $resultSetPrototype = new ResultSet();
                     return new TableGateway('login', $dbAdapter, null, $resultSetPrototype);
                     }
           ],
            ];
}

 public function getControllerConfig()
{
    return [
        'factories' => [
            Controller\AlbumController::class => function($container) {
              return new Controller\AlbumController($container->get(Model\AlbumTable::class));
            },
            Controller\LoginController::class => function($container)  {
              return new Controller\LoginController($container->get(Model\LoginTable::class));
            },
            Controller\LogoutController::class => function($container){
              return new Controller\LogoutController($container->get(Model\LoginTable::class));
            },
         ],
    ];
}
}
4

1 回答 1

0

这就是我实现它的方式。在您的Module.php中,添加一个侦听器EVENT_DISPATCH,并带有一个闭包作为回调,它将调用您的中间件类授权:

class Module implements ConfigProviderInterface
{
    public function getConfig()
    {
        return include __DIR__ . '/../config/module.config.php';
    }

    public function onBootstrap(MvcEvent $e)
    {
        $app = $e->getApplication();
        $eventManager = $app->getEventManager();
        $serviceManager = $app->getServiceManager();

        // Register closure on event DISPATCH, call your checkProtectedRoutes() method
        $eventManager->attach(MvcEvent::EVENT_DISPATCH, function (MvcEvent $e) use ($serviceManager) {
            $match = $e->getRouteMatch();
            $auth = $serviceManager->get(Middleware\AuthorizationMiddleware::class);
            $res = $auth->checkProtectedRoutes($match);
            if ($res instanceof Response) {
                return $res;
            }
        }, 1);

        // Init ACL : could be improved
        $this->initAcl($e);
    }

你应该有一个AuthorizationMiddlewareFactory(随意调用它):

<?php

namespace MyModule\Factory;

use Interop\Container\ContainerInterface;
use MyModule\Middleware\AuthorizationMiddleware;
use Zend\Authentication\AuthenticationService;
use Zend\ServiceManager\Factory\FactoryInterface;

class AuthorizationMiddlewareFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $authService = $container->get(AuthenticationService::class);
        $acl = $container->get('Acl');  // II init it in bootstrap(), could be improved
        $response = $container->get('Response');
        $baseUrl = $container->get('Request')->getBaseUrl();
        $authorization = new AuthorizationMiddleware($authService, $acl, $response, $baseUrl);
        return $authorization ;
    }
}

还有你的AuthorizationMiddleware课:

<?php

namespace MyModule\Middleware;

use Symfony\Component\VarDumper\VarDumper;
use Zend\Authentication\AuthenticationService;
use Zend\Http\PhpEnvironment\Response;
use Zend\Permissions\Acl\Acl;
use Zend\Router\RouteMatch;

class AuthorizationMiddleware
{
    private $authService ;
    private $acl;
    private $response;
    private $baseUrl;

    /**
     * AuthorizationMiddleware constructor.
     * @param AuthenticationService $authService
     * @param Acl $acl
     * @param Response $response
     * @param $baseUrl
     */
    public function __construct(AuthenticationService $authService, Acl $acl, Response $response, $baseUrl)
    {
        $this->authService = $authService;
        $this->acl = $acl;
        $this->response = $response;
        $this->baseUrl = $baseUrl;
    }

    public function checkProtectedRoutes(RouteMatch $match)
    {
        if (! $match) {
            // Nothing without a route
            return null ;
        }
        // Do your checks...
}

它可以改进,但你有这个想法......另请参阅此问题和答案:ACL 授权后的 ZF3 重定向失败

于 2016-09-27T17:50:44.733 回答