在其他框架里面,常命名为 beforeFilter(), afterFilter() 处理访问方法之前之后应该要做得操作, 在symfony里面没有直接提供这个入口方法, 只有通过添加监听器来实现。下面的例子为在访问方法之前验证签名操作。
1. 添加接口
- 让需要进行签名验证的控制器类实现该接口, 通过在监听器处判断当前正在访问的控制器对象是否该接口的实例,来判断是否需要进行签名验证。
//src/AppBundle/Controller/SignatureCheckController.php
<?php
namespace AppBundle\Controller;
interface SignatureCheckController
{
}
2. 添加监听器
//src/AppBundle/EventSubscriber/SignatureSubscriber.php
<?php
namespace AppBundle\EventSubscriber;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use AppBundle\Controller\SignatureCheckController;
/**
* 签名验证
* @author zhangshengji
*/
class SignatureSubscriber implements EventSubscriberInterface
{
private $privatekey;
public function __construct($privatekey)
{
$this->privatekey = $privatekey;
}
public function onKernelController(FilterControllerEvent $event)
{
$controller = $event->getController();
/*
* $controller passed can be either a class or a Closure.
* This is not usual in Symfony but it may happen.
* If it is a class, it comes in array format
*/
if (!is_array($controller)) {
return;
}
if ($controller[0] instanceof SignatureCheckController) {
exit("签名验证");
//签名验证
}
}
public static function getSubscribedEvents()
{
return array(
KernelEvents::CONTROLLER => 'onKernelController',
);
}
}
3. 将监听器注册成服务
- 这里使用手动注册服务的进行测试
- 修改parameters.yml配置文件, 增加privatekey作为签名验证秘钥
# This file is auto-generated during the composer install
parameters:
database_host:
database_port:
database_name:
database_user: root
database_password: 123456
mailer_transport: smtp
mailer_host: 127.0.0.1
mailer_user: null
mailer_password: null
secret: ThisTokenIsNotSoSecretChangeIt
privatekey: kkk
- 修改service.yml配置, 添加需要注册的服务
# 3.4配置
services:
# default configuration for services in *this* file
signatureCheckService:
class: AppBundle\EventSubscriber\SignatureSubscriber
autowire: true
autoconfigure: true
public: false
arguments:
$privatekey: "%privatekey%"
# 3.0配置
signatureCheckService:
class: AppBundle\EventListener\SignatureListener
arguments: ["%privatekey%"]
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
4. 添加测试控制器
//src/AppBundle/Controller/FooController.php
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
/**
* @Route("/foo")
*/
class FooController extends Controller implements SignatureCheckController
{
// An action that needs authentication
/**
* @Route("/bar")
*/
public function barAction(Request $request)
{
return new JsonResponse(['aa'=>1]);
}
}
测试
参考文档: http://symfony.com/doc/3.4/event_dispatcher/before_after_filters.html