更新时间:2023-11-19 15:42:04
正如我们之前谈到这个,你需要实施的EventListener
将倾听你的 onKernelRequest
。
As we talked about this before, you need to implement EventListener
which will listen to your onKernelRequest
.
在简单的英语,这意味着您的控制器操作的所有将执行 onKernelRequest
先给予访问原始控制器之前。所以,这样你就不必写
In plain English, this means that all of your Controller Actions will execute onKernelRequest
first before giving access to the original controller. So this way you won't have to write
/**
* @Security("has_role('ROLE_ADMIN')")
*/
在每个控制器动作。
现在,其高达你想要的在这个方法中做什么。我的方法是使该相关联的角色
与路线
表。该表将是比较大的,因为你必须包括所有的角色
你想给访问所有路线
。
Now, its upto you what you want to do in this method. My approach was to make a table which associates a ROLE
with a ROUTE
. This table will be comparatively big because you have to include all ROLES
you want to give access to all ROUTES
.
表结构可以是这样的:
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
文件中定义之一。如果你不知道,它看起来是这样的:
This way now only those roles are allowed to access contacts_lookup_homepage
route. Now on the onKernelRequest
all you will do is query this table and check if there is a match with that role with that route. You have access to both in this method. These routes are the same as the one you define in your routing.yml
file of every route. If you're not sure, it looks something like this:
contacts_lookup_homepage:
path: /Contacts/Lookup
defaults: { _controller: ContactsLookupBundle:Default:index }
现在终于在你的 onKernelRequest
你可以做这样的事情:
Now finally in your onKernelRequest
you can do something like this:
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 }
这将保证未经授权的用户访问未授权的控制器操作。我希望为您提供有关实施的想法。
This will guarantee that no unauthorized user accesses the controller action which is not authorized. I hope that gives you an idea about the implementation.