![](/img/trans.png)
[英]How to dynamic handle roles|permissions in Symfony2 at database level: CRUD operations over them
[英]How to dynamic handle roles|permissions in Symfony2: restrict functions with dynamic roles
這篇文章的目的是一種第二部分的這個職位,所以你可能要讀得懂這個問題。 擁有該信息和上一篇文章的答案,並且還發現了這個有用的UserBundle ,可以幫助我舉例說明roles
和users
之間可能存在的Many To Many
關系:
ROLES
? 我的意思是,例如,我想將現有功能限制為已動態創建的ROLE_NEWROLE
角色,因此在基礎代碼(原始源代碼)上不存在,那么如何將現有功能限制為該新角色? 以此處的文檔為例:
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
class PostController extends Controller
{
/**
* @Security("has_role('ROLE_ADMIN')")
*/
public function indexAction()
{
// ...
}
}
上面的代碼假定ROLE_ADMIN
已經在某處以某種方式聲明,但是如果我想通過安全組件將新的ROLE_NEWROLE
添加到該函數中怎么辦? 我是否需要一直觸摸我的代碼? 這一點都不好笑,所以我想知道您對這個話題的看法。
正如我們之前討論的那樣,您需要實現EventListener
,它將偵聽onKernelRequest
。
用簡單的英語來說,這意味着在授予對原始控制器的訪問權限之前, 所有控制器動作將首先執行onKernelRequest
。 這樣您就不必寫
/**
* @Security("has_role('ROLE_ADMIN')")
*/
在每個控制器動作中。
現在,取決於您要使用此方法執行的操作。 我的方法是制作一個將ROLE
與ROUTE
關聯的表。 該表將相對較大,因為您必須包括要授予所有ROUTES
訪問權限的所有ROLES
。
表結構可以是這樣的:
ACCESSID ROLENAME ROUTENAME
1 ROLE_NEWUSER contacts_lookup_homepage
2 ROLE_SUPER_USER contacts_lookup_homepage
根據此表,只有ROLE_NEWUSER
和ROLE_SUPER_USER
才有資格訪問路線contacts_lookup_homepage
現在,僅允許這些角色訪問contacts_lookup_homepage
路由。 現在,在onKernelRequest
上,您要做的就是查詢該表並檢查該角色與該路由是否匹配。 您可以使用此方法訪問兩者。 這些路由與您在每條路由的routing.yml
文件中定義的路由相同。 如果不確定,它看起來像這樣:
contacts_lookup_homepage:
path: /Contacts/Lookup
defaults: { _controller: ContactsLookupBundle:Default:index }
現在終於可以在onKernelRequest
中執行以下操作:
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
$route = $request->attributes->get('_route');
$routeArr = array('fos_js_routing_js', 'fos_user_security_login', '_wdt'); //These are excluded routes. These are always allowed. Required for login page
$roleArr = $this->token_storage->getToken()->getUser()->getRoles();
if(!is_int(array_search($route, $routeArr))) //This is for excluding routes that you don't want to check for.
{
//Check for a matching role and route
$qb = $this->em->getRepository('AppBundle:UserAccess')->createQueryBuilder('o');
$qb
->select('o')
->where('o.ROLENAME IN (:roleArr)')
->setParameter('roleArr', $roleArr)
->andWhere('o.ROUTENAME = :route')
->setParameter('route', $route)
;
$result = $qb->getQuery()->getArrayResult();
if(empty($result))
{
//A matching role and route was not found so we do not give access to the user here and redirect to another page.
$event->setResponse(new RedirectResponse($this->router->generate('user_management_unauthorized_user', array())));
}
}
}
services.yml
可以像這樣:
services:
app.tokens.action_listener:
class: EventListenerBundle\EventListener\TokenListener
arguments:
entityManager: "@doctrine.orm.entity_manager"
token_storage: "@security.token_storage"
templating: "@templating"
router: "@router"
resolver: "@controller_resolver"
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
這將確保沒有未經授權的用戶訪問未經授權的控制器操作。 希望您能對實現有所了解。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.