A free and open-source book on ZF3 for beginners


17.12. Модифицируем сервис AuthManager

Следующее, что мы сделаем, – модифицируем фильтр доступа в сервисе AuthManager, который мы написали для примера User Demo. В частности, мы хотим изменить метод filterAccess(). Мы хотим, чтобы этот метод использовал наш класс RbacManager.

Но сначала изменим формат ключа access_filter в конфигурации. Мы хотим, чтобы этот ключ позволял разрешать доступ:

Вот так, например, будет выглядеть ключ access_filter для модуля User:

<?php
return [
    //...

    // Ключ 'access_filter' используется модулем User для запрета или разрешения
    // доступа к определенным действиям контроллера для неавторизованных посетителей.
    'access_filter' => [
        'controllers' => [
            Controller\UserController::class => [
                // Дать доступ к действиям "resetPassword", "message" и "setPassword" всем.
                ['actions' => ['resetPassword', 'message', 'setPassword'], 'allow' => '*'],
                // Дать доступ к действиям "index", "add", "edit", "view", "changePassword" 
                // пользователям с привилегией "user.manage".
                ['actions' => ['index', 'add', 'edit', 'view', 'changePassword'], 
                 'allow' => '+user.manage']
            ],
            Controller\RoleController::class => [
                // Разрешить доступ аутентифицированным пользователям с привилегией "role.manage".
                ['actions' => '*', 'allow' => '+role.manage']
            ],
            Controller\PermissionController::class => [
                // Разрешить доступ аутентифицированным пользователям с привилегией "permission.manage".
                ['actions' => '*', 'allow' => '+permission.manage']
            ],
        ]
    ],
    
    //...
];

Ниже вы можете найти исходный код метода filterAccess() сервиса AuthManager:

/**
 * Это простой фильтр контроля доступа. Он может ограничивать доступ к определенным страницам
 * для неавторизованных пользователей.
 * 
 * Данный метод использует ключ в файле конфигурации и определяет, разрешен ли
 * текущему посетителю доступ к заданному действию контроллера или нет. Если разрешен,
 * он возвращает true, в противном случае – false.
 */
public function filterAccess($controllerName, $actionName)
{
    // Определяем режим – 'ограничительный' (по умолчанию) или 'разрешительный'. В ограничительном
    // режиме все действия контроллера должны быть явно перечислены под ключом конфигурации 'access_filter',
    // и доступ к любому не указанному действию для неавторизованных пользователей запрещен. 
    // В разрешительном режиме, если действие не указано под ключом 'access_filter', доступ к нему 
    // разрешен для всех (даже для незалогиненных пользователей).
    // Ограничительный режим является более безопасным, и рекомендуется использовать его.
    $mode = isset($this->config['options']['mode'])?$this->config['options']['mode']:'restrictive';
    if ($mode!='restrictive' && $mode!='permissive')
        throw new \Exception('Invalid access filter mode (expected either restrictive or permissive mode');
    
    if (isset($this->config['controllers'][$controllerName])) {
        $items = $this->config['controllers'][$controllerName];
        foreach ($items as $item) {
            $actionList = $item['actions'];
            $allow = $item['allow'];
            if (is_array($actionList) && in_array($actionName, $actionList) ||
                $actionList=='*') {
                if ($allow=='*')
                    // Все могут просматривать эту страницу.
                    return self::ACCESS_GRANTED; 
                else if (!$this->authService->hasIdentity()) {
                    // Только аутентифицированные пользователи могут просматривать страницу.
                    return self::AUTH_REQUIRED;                        
                }
                    
                if ($allow=='@') {
                    // Любой аутентифицированный пользователь может просматривать страницу.
                    return self::ACCESS_GRANTED;                         
                } else if (substr($allow, 0, 1)=='@') {
                    // Только пользователи с определенной привилегией могут просматривать страницу.
                    $identity = substr($allow, 1);
                    if ($this->authService->getIdentity()==$identity)
                        return self::ACCESS_GRANTED; 
                    else
                        return self::ACCESS_DENIED;
                } else if (substr($allow, 0, 1)=='+') {
                    // Только пользователи с этой привилегией могут просматривать страницу.
                    $permission = substr($allow, 1);
                    if ($this->rbacManager->isGranted(null, $permission))
                        return self::ACCESS_GRANTED; 
                    else
                        return self::ACCESS_DENIED;
                } else {
                    throw new \Exception('Unexpected value for "allow" - expected ' .
                            'either "?", "@", "@identity" or "+permission"');
                }
            }
        }            
    }
    
    // В ограничительном режиме мы требуем аутентификации для любого действия, не 
    // перечисленного под ключом 'access_filter' и отказываем в доступе авторизованным пользователям
    // (из соображений безопасности).
    if ($mode=='restrictive') {
        if(!$this->authService->hasIdentity())
            return self::AUTH_REQUIRED;
        else
            return self::ACCESS_DENIED;
    }
    
    // Разрешить доступ к этой странице.
    return self::ACCESS_GRANTED;
}

Как вы могли видеть из кода выше, метод возвращает одну из трех констант:


Top