Следующее, что мы сделаем, – модифицируем фильтр доступа в сервисе AuthManager
, который мы
написали для примера User Demo. В частности, мы хотим изменить метод filterAccess()
.
Мы хотим, чтобы этот метод использовал наш класс RbacManager
.
Но сначала изменим формат ключа access_filter
в конфигурации. Мы хотим, чтобы этот ключ позволял
разрешать доступ:
*
);@
);личности
, если мы поставим (@identity
)привилегией
, если мы поставим знак плюса и имя привилегии (+permission
).Вот так, например, будет выглядеть ключ 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;
}
Как вы могли видеть из кода выше, метод возвращает одну из трех констант:
ACCESS_GRANTED
, если пользователю разрешено просматривать данную страницу;AUTH_REQUIRED
, если пользователю сперва нужно пройти аутентификацию;ACCESS_DENIED
, если пользователю запрещено просматривать данную страницу.