Есть ли способ ограничить доступ к определенным маршрутам, иначе действие / метод контроллера в Symfony на основе пользователя?
Я реализую FOSUserBundle для управления пользователями, и у него есть роли для определения разрешений, которые хорошо работают, если у меня есть пользователь с определенными ролями, но если я хочу ограничить страницу на основе пользователей, мне нужно создать роль для каждого маршрута или есть какой-то лучший подход.
Я посмотрел в ACL и его идеально подходит, но я не могу найти решение для моего дела, или я что-то там упустил.
Нужны помощь и идеи.
Обновления
@ AJ Cerqueti — Ответ может быть быстро исправлен, но я ищу лучший подход, если таковой имеется.
Чтобы быть более конкретным, можно назначить пользователю права доступа для маршрутов, используя ACL или какой-то другой более подходящий подход.
SYMFONY> = 2.6
Symfony <= 2.5
Для простых нужд, как это вы можете создать охранного избирателя которые точно соответствуют вашим потребностям (списки ACL обычно используются для сложных задач, в том числе из-за непростой реализации).
Затем вы можете использовать избирателя в вашем контроллере, как описано в документации:
// get a Post instance
$post = ...;
// keep in mind, this will call all registered security voters
if (false === $this->get('security.authorization_checker')->isGranted('view', $post)) {
throw new AccessDeniedException('Unauthorised access!');
}
Читайте также Как использовать избирателей для проверки прав пользователей
ОБНОВЛЕНИЕ НА ОСНОВЕ КОММЕНТАРИИ:
Возможно, будет лучше узнать, на скольких маршрутах вы хотите добавить это поведение, но в любом случае (и если вы хотите избежать добавления в каждый контроллер кода @AJCerqueti), вы можете использовать Voter, как в этом простом примере:
Класс избирателя:
// src/AppBundle/Security/Authorization/Voter/RouteVoter.php
namespace AppBundle\Security\Authorization\Voter;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
class RouteVoter implements VoterInterface
{
private $routes;
public function __construct(array $routes = array())
{
$this->routes = $routes;
}
public function supportsAttribute($attribute)
{
// you won't check against a user attribute, so return true
return true;
}
public function supportsClass($class)
{
// your voter supports all type of token classes, so return true
return true;
}
public function vote(TokenInterface $token, $object, array $attributes)
{
// get get allowed routes from current logged in user
$userRoutes = $token->getUser()->getRoutes();
// implement as you want the checks and return the related voter constant as below
if (...) {# your implementation
return VoterInterface::ACCESS_DENIED;
}
return VoterInterface::ACCESS_ABSTAIN;
}
}
Зарегистрировать избирателя:
<service id="security.access.route_voter"class="AppBundle\Security\Authorization\Voter\RouteVoter" public="false">
<argument type="collection">
<argument>route_one</argument>
<argument>route_two</argument>
</argument>
<tag name="security.voter" />
Теперь измените стратегию принятия решения в соответствии с документами.
Может ли это соответствовать вашим потребностям?
Согласитесь с предыдущими ответами о том, что списки ACL, избиратели или какое-либо решение на основе ролей определенно является подходом наилучшей практики, но для этого дополнительного случая предложило бы расширить FOSUser, добавив поле ‘slug’, и затем проверить это:
if('accessible_slug' !== $this->get('security.context')->getToken()->getUser()->getSlug()) {
throw new AccessDeniedException()
}
Это означает, что нужно настроить слаг для групп контроллеров / действий и настроить их для пользователя. Подобно ролям, но без лишних накладных расходов. Все еще предпочитают Избирателей и какую-то иерархию ролей, но надеюсь, что это поможет.
Ты можешь использовать AccessDeniedException Symfony2
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
Затем проверьте, залогинен ли пользователь,
if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedException();
} else {
Continue;
}
В app/config/security.yml
есть раздел access_control:
, Там вы можете определить ограничения доступа для конкретных путей, например.
- { path: ^/faq/admin, roles: ROLE_FAQ_ADMIN }
path
Аргумент является регулярным выражением, поэтому приведенная выше запись ограничит доступ к любому пути, начинающемуся с /faq/admin
например /faq/admin/show-something
, /faq/admin/show-something-else
и т.д. Только пользователи с указанной ролью будут иметь доступ к этим путям. Для других пользователей AccessDeniedException
будет брошен с HTTP-кодом 403.
Нет необходимости изменять код в действиях внутри контроллеров.