有没有办法根据用户限制对特定路由的访问,也就是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()
}
这意味着为控制器/操作组设置一个 slug,并将它们设置为用户。与角色类似,但没有那么多开销。仍然更喜欢选民和某种角色层次结构,但希望这有所帮助。
您可以使用 Symfony2 的 AccessDeniedException
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抛出。
无需更改控制器内部操作中的代码。