如何限制 action/method(控制器)对 Symfony 中特定用户的访问?
How to restrict access of action/method (of Controller) to specific user in Symfony?
有没有办法根据用户限制对 Symfony 中控制器的特定路由又名 action/method 的访问?
我正在实施 FOSUserBundle 进行用户管理,它具有用于定义权限的角色,如果我的用户具有已定义的角色,则效果很好,但如果我想根据用户限制页面,我必须为每条路线创建角色,或者是还有更好的办法吗
我已经研究了 ACL 及其完美,但我没有找到适合我的情况的解决方案,或者我在那里遗漏了什么。
寻求一些帮助和想法。
更新
@AJ Cerqueti - 答案可以快速解决,但我正在寻找更好的方法。
更具体地说,是否可以使用 ACL 或其他更好的方法为用户分配路由访问权限。
你可以使用 Symfony2
的 AccessDeniedException
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
然后检查登录用户,
if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedException();
} else {
Continue;
}
SYMFONY >=2.6
- create a security voter
- How to Use Voters to Check User Permissions
- Now change the access decision strategy accordingly with the docs
SYMFONY <=2.5
对于像这样的简单需求,您可以 create a security voter 完全满足您的需求(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!');
}
另读How to Use Voters to Check User Permissions
根据评论更新:
也许最好知道要添加此行为的路由数量,但无论如何(如果您想避免在每个控制器中添加@AJCerqueti 代码)您可以使用像这样的投票器简单示例:
选民Class:
// 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" />
Now change the access decision strategy accordingly with the docs.
这能满足您的需求吗?
同意之前的回答,即 ACL、选民或某种基于角色的解决方案绝对是最佳实践方法,但对于这种边缘情况,建议扩展您的 FOSUser 以添加 'slug' 字段,并且然后检查一下:
if('accessible_slug' !== $this->get('security.context')->getToken()->getUser()->getSlug()) {
throw new AccessDeniedException()
}
这意味着为 controllers/actions 组设置一个 slug,并将它们设置给用户。类似于角色,但没有那么多的开销。仍然更喜欢选民和某种角色层次结构,但希望这会有所帮助。
在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。
无需更改控制器内部操作中的代码。
有没有办法根据用户限制对 Symfony 中控制器的特定路由又名 action/method 的访问?
我正在实施 FOSUserBundle 进行用户管理,它具有用于定义权限的角色,如果我的用户具有已定义的角色,则效果很好,但如果我想根据用户限制页面,我必须为每条路线创建角色,或者是还有更好的办法吗
我已经研究了 ACL 及其完美,但我没有找到适合我的情况的解决方案,或者我在那里遗漏了什么。
寻求一些帮助和想法。
更新
@AJ Cerqueti - 答案可以快速解决,但我正在寻找更好的方法。
更具体地说,是否可以使用 ACL 或其他更好的方法为用户分配路由访问权限。
你可以使用 Symfony2
的 AccessDeniedExceptionuse Symfony\Component\Security\Core\Exception\AccessDeniedException;
然后检查登录用户,
if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedException();
} else {
Continue;
}
SYMFONY >=2.6
- create a security voter
- How to Use Voters to Check User Permissions
- Now change the access decision strategy accordingly with the docs
SYMFONY <=2.5
对于像这样的简单需求,您可以 create a security voter 完全满足您的需求(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!');
}
另读How to Use Voters to Check User Permissions
根据评论更新:
也许最好知道要添加此行为的路由数量,但无论如何(如果您想避免在每个控制器中添加@AJCerqueti 代码)您可以使用像这样的投票器简单示例:
选民Class:
// 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" />
Now change the access decision strategy accordingly with the docs.
这能满足您的需求吗?
同意之前的回答,即 ACL、选民或某种基于角色的解决方案绝对是最佳实践方法,但对于这种边缘情况,建议扩展您的 FOSUser 以添加 'slug' 字段,并且然后检查一下:
if('accessible_slug' !== $this->get('security.context')->getToken()->getUser()->getSlug()) {
throw new AccessDeniedException()
}
这意味着为 controllers/actions 组设置一个 slug,并将它们设置给用户。类似于角色,但没有那么多的开销。仍然更喜欢选民和某种角色层次结构,但希望这会有所帮助。
在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。
无需更改控制器内部操作中的代码。