如何设置前后过滤器
编辑本页警告:您正在浏览的文档欧宝体育电话欧宝娱乐app下载地址Symfony 3.1,现已不再维护。
读本页的更新版本用于Sy欧宝娱乐app下载地址mfony 6.2(当前稳定版本)。
如何设置前后过滤器
在web应用程序开发中,需要在充当过滤器或钩子的控制器操作之前或之后执行一些逻辑是非常常见的。
一些web框架定义了像这样的方法preExecute ()
而且postExecute ()
但在Symfony没有这样的东西。欧宝娱乐app下载地址方法可以干扰Req欧宝app在哪里找uest ->响应过程,这是一个更好的方法EventDispatcher组件.
令牌验证示例
想象一下,您需要开发一个API,其中一些控制器是公共的,而另一些则仅限于一个或几个客户端。对于这些私有特性,您可以向客户端提供一个令牌来标识自己。
因此,在执行控制器动作之前,您需要检查该动作是否受到限制。如果它受到限制,则需要验证所提供的令牌。
请注意
请注意,为了简单起见,将在配置中定义令牌,并且不使用数据库设置或通过Security组件进行身份验证。
在使用kernel.controller
事件
首先,使用存储一些基本令牌配置config.yml
参数键:
- YAML
- XML
- PHP
1 2 3 4 5
# app / config / config.yml参数:令牌:client1:pass1作为client2:pass2
1 2 3 4 5 6 7
<!--app/config/config.xml --><参数><参数关键=“令牌”类型=“收集”><参数关键=“client1”>pass1作为参数><参数关键=“client2”>pass2参数>参数>参数>
1 2 3 4 5
/ / app / config / config . php$容器->setParameter (“令牌”,数组(“client1”= >“pass1作为”,“client2”= >“pass2”));
标签控制器要检查
一个kernel.controller
监听器收到关于每一个请求,在控制器执行之前。因此,首先,您需要某种方法来识别匹配请求的控制器是否需要令牌验证。
一个干净简单的方法是创建一个空接口,并让控制器实现它:
1 2 3 4 5 6
名称空间AppBundle\控制器;接口TokenAuthenticatedController{/ /……}
实现这个接口的控制器看起来就像这样:
12 3 4 5 6 7 8 9 10 11 12 13
名称空间AppBundle\控制器;使用AppBundle\控制器\TokenAuthenticatedController;使用欧宝娱乐app下载地址\包\FrameworkBundle\控制器\控制器;类FooController扩展控制器实现了TokenAuthenticatedController{//需要验证的动作公共函数barAction(){/ /……}}
创建事件监听器
接下来,您需要创建一个事件侦听器,它将保存您希望在控制器之前执行的逻辑。如果您不熟悉事件侦听器,您可以在事件和事件监听器:
12 34 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
/ / src / AppBundle / EventListener / TokenListener.php名称空间AppBundle\EventListener;使用AppBundle\控制器\TokenAuthenticatedController;使用欧宝娱乐app下载地址\组件\HttpKernel\异常\AccessDeniedHttpException;使用欧宝娱乐app下载地址\组件\HttpKernel\事件\FilterControllerEvent;类TokenListener{私人$令牌;公共函数__construct($令牌){$这->令牌=$令牌;}公共函数onKernelController(FilterControllerEvent$事件){$控制器=$事件->getController ();/* * $controller可以是一个类或闭包。*这在Symfony中并不常见,但可能会发生。欧宝娱乐app下载地址*如果它是一个类,它以数组格式*/出现如果(!is_array ($控制器)) {返回;}如果($控制器[0]运算符TokenAuthenticatedController) {$令牌=$事件->getRequest ()->查询->get (“令牌”);如果(!in_array ($令牌,$这->令牌)){扔新AccessDeniedHttpException (“这个动作需要一个有效的令牌!”);} } } }
注册监听器
最后,将侦听器注册为服务,并将其标记为事件侦听器。通过听kernel.controller
,您告诉Symfony您希望在任何欧宝娱乐app下载地址控制器执行之前调用侦听器。
- YAML
- XML
- PHP
1 2 3 4 5 6 7
# app / config / services.yml服务:app.tokens.action_listener:类:AppBundle \ EventListener \ TokenListener参数:[' %符号% ')标签:-{名称:kernel.event_listener,事件:kernel.controller,方法:onKernelController}
1 2 3 4 5
<!--app/config/services.xml --><服务id=“app.tokens.action_listener”类=“AppBundle \ EventListener \ TokenListener”><论点>%符号%论点><标签的名字=“kernel.event_listener”事件=“kernel.controller”方法=“onKernelController”/>服务>
1 2 3 4 5 6 7 8 9 10
/ / app / config / services.php使用AppBundle\EventListener\TokenListener;使用欧宝娱乐app下载地址\组件\DependencyInjection\定义;$侦听器=新定义(TokenListener::类,数组(“%符号%”));$侦听器->addTag (“kernel.event_listener”,数组(“事件”= >“kernel.controller”,“方法”= >“onKernelController”));$容器->setDefinition (“app.tokens.action_listener”,$侦听器);
有了这个配置,您的TokenListener
onKernelController ()
方法将在每个请求上执行。如果即将被执行的控制器实现TokenAuthenticatedController
,采用token认证。这让你可以在任何你想要的控制器上使用“before”过滤器。
After Filters使用kernel.response
事件
除了有一个被执行的“钩子”之前你的控制器,你也可以添加一个被执行的钩子后你的控制器。对于这个示例,假设您想要向所有通过此令牌身份验证的响应添加sha1哈希(使用该令牌的盐)。
Symfony的另一个核心欧宝娱乐app下载地址事件——叫kernel.response
-在每个请求时都被通知,但在控制器返回一个Response对象之后。创建“after”侦听器与创建侦听器类并将其注册为此事件的服务一样简单。
例如,以TokenListener
从前面的示例中,首先记录请求属性中的身份验证令牌。这将作为这个请求进行令牌认证的基本标志:
12 3 4 5 6 7 8 9 10 11 12 13 14
公共函数onKernelController(FilterControllerEvent$事件){/ /……如果($控制器[0]运算符TokenAuthenticatedController) {$令牌=$事件->getRequest ()->查询->get (“令牌”);如果(!in_array ($令牌,$这->令牌)){扔新AccessDeniedHttpException (“这个动作需要一个有效的令牌!”);}//将请求标记为已通过token身份验证$事件->getRequest ()->属性->集(“auth_token”,$令牌);}}
现在,向这个类添加另一个方法-onKernelResponse ()
-在请求对象上寻找这个标志,如果找到了,就在响应上设置自定义报头:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16
//在文件顶部添加新的use语句使用欧宝娱乐app下载地址\组件\HttpKernel\事件\FilterResponseEvent;公共函数onKernelResponse(FilterResponseEvent$事件){//检查onKernelController是否将此标记为标记“auth'ed”请求如果(!$令牌=$事件->getRequest ()->属性->get (“auth_token”)) {返回;}$响应=$事件->getResponse ();//创建一个散列并将其设置为响应头$哈希= sha1 ($响应->getContent()。$令牌);$响应->头->集(“X-CONTENT-HASH”,$哈希);}
最后,在服务定义中需要第二个“标记”来通知Symfony欧宝娱乐app下载地址onKernelResponse
事件的通知kernel.response
事件:
- YAML
- XML
- PHP
1 2 3 4 5 6 7 8
# app / config / services.yml服务:app.tokens.action_listener:类:AppBundle \ EventListener \ TokenListener参数:[' %符号% ')标签:-{名称:kernel.event_listener,事件:kernel.controller,方法:onKernelController}-{名称:kernel.event_listener,事件:kernel.response,方法:onKernelResponse}
1 2 3 4 5 6
<!--app/config/services.xml --><服务id=“app.tokens.action_listener”类=“AppBundle \ EventListener \ TokenListener”><论点>%符号%论点><标签的名字=“kernel.event_listener”事件=“kernel.controller”方法=“onKernelController”/><标签的名字=“kernel.event_listener”事件=“kernel.response”方法=“onKernelResponse”/>服务>
12 3 4 5 6 7 8 9 10 11 12 13 14
/ / app / config / services.php使用AppBundle\EventListener\TokenListener;使用欧宝娱乐app下载地址\组件\DependencyInjection\定义;$侦听器=新定义(TokenListener::类,数组(“%符号%”));$侦听器->addTag (“kernel.event_listener”,数组(“事件”= >“kernel.controller”,“方法”= >“onKernelController”));$侦听器->addTag (“kernel.event_listener”,数组(“事件”= >“kernel.response”,“方法”= >“onKernelResponse”));$容器->setDefinition (“app.tokens.action_listener”,$侦听器);
就是这样!的TokenListener
现在在每个控制器执行之前被通知(onKernelController ()
),在每个控制器返回一个响应后(onKernelResponse ()
).通过使特定的控制器实现TokenAuthenticatedController
接口,你的监听器知道它应该在哪个控制器上执行操作。通过在请求的“attributes”包中存储一个值,则onKernelResponse ()
方法知道如何添加额外的标头。玩得开心!