如何设置前后过滤器
编辑本页警告:您正在浏览的文档欧宝体育电话欧宝娱乐app下载地址Symfony 4.1,现已不再维护。
读本页的更新版本用于Sy欧宝娱乐app下载地址mfony 6.2(当前稳定版本)。
如何设置前后过滤器
在web应用程序开发中,需要在充当过滤器或钩子的控制器操作之前或之后执行一些逻辑是非常常见的。
一些web框架定义了像这样的方法preExecute ()
而且postExecute ()
但在Symfony没有这样的东西。欧宝娱乐app下载地址方法可以干扰Req欧宝app在哪里找uest ->响应过程,这是一个更好的方法EventDispatcher组件.
令牌验证示例
想象一下,您需要开发一个API,其中一些控制器是公共的,而另一些则仅限于一个或几个客户端。对于这些私有特性,您可以向客户端提供一个令牌来标识自己。
因此,在执行控制器动作之前,您需要检查该动作是否受到限制。如果它受到限制,则需要验证所提供的令牌。
请注意
请注意,为了简单起见,将在配置中定义令牌,并且不使用数据库设置或通过Security组件进行身份验证。
在使用kernel.controller
事件
首先,将一些令牌配置定义为参数:
- YAML
- XML
- PHP
1 2 3 4 5
#配置/ services.yaml参数:令牌:client1:pass1作为client2:pass2
12 3 4 5 6 7 8 9 10 11 12 13 14
<!——config/services.xml——> .xml<??> . xml version="1.0" encoding="UTF-8"<容器xmlns=“http://欧宝娱乐app下载地址www.oldmanjams.com/schema/dic/services”xmlns: xsi=“http://www.w3.org/2001/XMLSchema-instance”xsi: schemaLocation=“http://欧宝娱乐app下载地址www.oldmanjams.com/schema/dic/services //www.oldmanjams.com/schema/dic/services/services-1.0.xsd”><参数><参数关键=“令牌”类型=“收集”><参数关键=“client1”>pass1作为参数><参数关键=“client2”>pass2参数>参数>参数>容器>
1 2 3 4 5
/ /配置/ services.php$容器->setParameter (“令牌”, (“client1”= >“pass1作为”,“client2”= >“pass2”]);
标签控制器要检查
一个kernel.controller
(又名KernelEvents:控制器
)监听器得到通知每一个请求,在控制器执行之前。因此,首先,您需要某种方法来识别匹配请求的控制器是否需要令牌验证。
一个干净简单的方法是创建一个空接口,并让控制器实现它:
1 2 3 4 5 6
名称空间应用程序\控制器;接口TokenAuthenticatedController{/ /……}
实现这个接口的控制器是这样的:
12 3 4 5 6 7 8 9 10 11 12 13
名称空间应用程序\控制器;使用应用程序\控制器\TokenAuthenticatedController;使用欧宝娱乐app下载地址\包\FrameworkBundle\控制器\AbstractController;类FooController扩展AbstractController实现了TokenAuthenticatedController{//需要验证的动作公共函数酒吧(){/ /……}}
创建事件订阅服务器
接下来,您需要创建一个事件订阅器,该订阅器将保存您希望在控制器之前执行的逻辑。如果您不熟悉事件订阅者,可以在事件和事件监听器:
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 38 39 40 41 42 43 44 45 46
/ / src / EventSubscriber / TokenSubscriber.php名称空间应用程序\EventSubscriber;使用应用程序\控制器\TokenAuthenticatedController;使用欧宝娱乐app下载地址\组件\HttpKernel\异常\AccessDeniedHttpException;使用欧宝娱乐app下载地址\组件\HttpKernel\事件\FilterControllerEvent;使用欧宝娱乐app下载地址\组件\EventDispatcher\EventSubscriberInterface;使用欧宝娱乐app下载地址\组件\HttpKernel\KernelEvents;类TokenSubscriber实现了EventSubscriberInterface{私人$令牌;公共函数__construct($令牌){$这->令牌=$令牌;}公共函数onKernelController(FilterControllerEvent$事件){$控制器=$事件->getController ();/* * $controller可以是一个类或闭包。*这在Symfony中并不常见,但可能会发生。欧宝娱乐app下载地址*如果它是一个类,它以数组格式*/出现如果(!is_array ($控制器)) {返回;}如果($控制器[0]运算符TokenAuthenticatedController) {$令牌=$事件->getRequest ()->查询->get (“令牌”);如果(!in_array ($令牌,$这->令牌)){扔新AccessDeniedHttpException (“这个动作需要一个有效的令牌!”);}}}公共静态函数getSubscribedEvents(){返回[KernelEvents::控制器= >“onKernelController”,);}}
就是这样!你的services.yaml
文件应已设置,以便从EventSubscriber
目录中。欧宝娱乐app下载地址Symfony负责其余的工作。你的TokenSubscriber
onKernelController ()
方法将在每个请求上执行。如果即将被执行的控制器实现TokenAuthenticatedController
,采用token认证。这让你可以在任何你想要的控制器上使用“before”过滤器。
提示
如果您的订户是不每次请求都打电话,仔细检查你是否加载服务从EventSubscriber
目录和有可以使用autoconfigure启用。也可以手动添加kernel.event_subscriber
标签。
After Filters使用kernel.response
事件
除了有一个被执行的“钩子”之前你的控制器,你也可以添加一个被执行的钩子后你的控制器。对于这个示例,假设您想要向所有通过此令牌身份验证的响应添加sha1哈希(使用该令牌的盐)。
Symfony的另一个核心欧宝娱乐app下载地址事件——叫kernel.response
(又名KernelEvents:响应
) -在每个请求时都会被通知,但是在控制器返回一个Response对象之后。要创建一个“after”侦听器,请创建一个侦听器类,并将其注册为此事件的服务。
例如,以TokenSubscriber
从前面的示例中,首先记录请求属性中的身份验证令牌。这将作为这个请求进行令牌认证的基本标志:
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 ()
.它会寻找auth_token
在请求对象上标记,并在响应上设置自定义报头,如果找到它:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
//在文件顶部添加新的use语句使用欧宝娱乐app下载地址\组件\HttpKernel\事件\FilterResponseEvent;公共函数onKernelResponse(FilterResponseEvent$事件){//检查onKernelController是否将此标记为标记“auth'ed”请求如果(!$令牌=$事件->getRequest ()->属性->get (“auth_token”)) {返回;}$响应=$事件->getResponse ();//创建一个散列并将其设置为响应头$哈希= sha1 ($响应->getContent()。$令牌);$响应->头->集(“X-CONTENT-HASH”,$哈希);}公共静态函数getSubscribedEvents(){返回[KernelEvents::控制器= >“onKernelController”, KernelEvents::响应= >“onKernelResponse”,);}
就是这样!的TokenSubscriber
现在在每个控制器执行之前被通知(onKernelController ()
),在每个控制器返回一个响应后(onKernelResponse ()
).通过使特定的控制器实现TokenAuthenticatedController
接口,你的监听器知道它应该在哪个控制器上执行操作。通过在请求的“attributes”包中存储一个值,则onKernelResponse ()
方法知道如何添加额外的标头。玩得开心!