[英]how to add user roles dynamically upon login with symfony2 (and fosUserBundle)?
[英]How I can add a “roles” to a “path” dynamically in Symfony2?
根据站点本身的文档,在 SF2 中我有以下场景:
security:
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_ADMIN }
我需要手动添加可以访问此“路径”的每个“路径”和“角色”。 我怎样才能动态地做到这一点? 像 Yii2 上的 RBAC:
SF2 自己的文档中是否有任何现成的 Bundle 或其他内容允许这样做? 作为假设的例子:
security:
access_control:
type: dynamically
如果您想让添加角色更容易,您可以使用注释。
您的问题要求动态安全性,这很复杂。 路由和所有角色在缓存预热阶段编译。 因此,要使其正常工作,您首先需要存储动态值。 数据库将是一个不错的选择。 在这里,我只展示如何检查角色,实际的角色操作我将留给您。
最简单的方法是将授权检查器注入您的控制器。
services:
acme_controller:
class: "AcmeDemoBundle\Controller"
arguments: ["@security.authorization_checker"]
然后检查操作中的角色:
public function __construct(AuthorizationCheckerInterface $authorizationChecker)
{
$this->authorizationChecker = $authorizationChecker;
}
public function listAction()
{
$role = /* load your role here */;
if (false === $this->authorizationChecker->isGranted($role)) {
throw new AccessDeniedException();
}
// ...
}
如果您希望在许多控制器中使用上述代码,则会导致重复代码,因此您还可以创建一个投票者:
services:
acme.route.voter:
class: AcmeDemoBundle\RouteVoter
arguments:
- @security.role_hierarchy
public: false
tags:
- { name: security.voter, priority: 300 }
例子:
public function __construct ( RoleHierarchyInterface $roleHierarchy )
{
$this->roleVoter = new RoleHierarchyVoter( $roleHierarchy );
}
public function vote ( TokenInterface $token, $object, array $attributes )
{
if ( !$object instanceof Request ) {
return VoterInterface::ACCESS_ABSTAIN;
}
$requestUri = $object->getPathInfo();
if ( isset($this->votes[ $requestUri ]) ) {
return $this->votes[ $requestUri ];
}
$roles = /* load your roles */;
return $this->votes[ $requestUri ] = $this->roleVoter->vote( $token, $object, $roles );
}
另一种方法是用您自己的实现替换router
服务。 这是我的CMF Bundle所采用的方法。
您可以像这样动态管理角色/路由关系:
您在内核上创建一个侦听器
<service id="toto.security.controller_listener" class="Administration\SecurityBundle\EventListener\SecurityListener">
<tag name="kernel.event_listener" event="kernel.controller" method="onKernelController" />
<argument type="service" id="service_container" />
</service>
然后在监听器中实现这个方法
public function onKernelController(FilterControllerEvent $event)
{
$controller = $event->getController();
if (!is_array($controller)) {
return;
}
$request = $event->getRequest();
$baseUrl = $request->getBaseUrl();
$requestUri = $request->getRequestUri();
$route = str_replace($baseUrl, "", $requestUri);
//you put your check logic
//you can implement a relation beetween routes and roles/ users in database etc. you got the entire control on what you do
if(!$this->accessMananager->isGrantAccess(User $user, $route)){
throw new AccessDeniedException("blah blah blah")
}
}
由于此侦听器将始终在您的任何控制器之前调用,请考虑创建一个缓存系统
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.