可能咱們在某些時候須要在某一個動做先後執行一些邏輯一個;咱們能夠經過事件機制來完成php
##一個Token驗證的例子數據庫
假如你開發了一個API;有的資源能對外開放;有的須要驗證才能訪問資源;這就須要咱們對請求來判斷是否訪問了須要的資源;以及他們所攜帶的token是否正確app
####使用kernel.controller事件來前置過濾器this
定義一些對外的token參數;注意這些也能夠在數據庫中配置加密
# app/config/config.yml parameters: tokens: client1: pass1 client2: pass2
定義一個接口;以便區分哪些控制器須要驗證spa
namespace AppBundle\Controller; interface TokenAuthenticatedController { // ... }
定義控制器;實現了上述的接口的控制器就須要驗證才能訪問code
namespace AppBundle\Controller; use AppBundle\Controller\TokenAuthenticatedController; use Symfony\Bundle\FrameworkBundle\Controller\Controller; class FooController extends Controller implements TokenAuthenticatedController { // An action that needs authentication public function barAction() { // ... } }
####建立一個事件監聽者orm
// src/AppBundle/EventListener/TokenListener.php namespace AppBundle\EventListener; use AppBundle\Controller\TokenAuthenticatedController; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Event\FilterControllerEvent; class TokenListener { private $tokens; public function __construct($tokens) { $this->tokens = $tokens;#構造注入 } 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; } //驗證傳入的token是否正確 if ($controller[0] instanceof TokenAuthenticatedController) { $token = $event->getRequest()->query->get('token'); if (!in_array($token, $this->tokens)) { throw new AccessDeniedHttpException('This action needs a valid token!'); } } } }
####註冊監聽者token
# app/config/services.yml services: app.tokens.action_listener: class: AppBundle\EventListener\TokenListener arguments: ['%tokens%']#把上面配置的tokens參數注入給監聽者類 tags: - { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
###使用kernel.response事件構造後置過濾器接口
假如咱們上面的例子;客戶token正確;訪問資源完畢;咱們須要回調給客戶數據;客戶那邊也須要驗證; 這時候咱們就可使用 該事件了;
//這是kernel.controller事件調用 public function onKernelController(FilterControllerEvent $event) { // ... if ($controller[0] instanceof TokenAuthenticatedController) { $token = $event->getRequest()->query->get('token'); if (!in_array($token, $this->tokens)) { throw new AccessDeniedHttpException('This action needs a valid token!'); } //驗證經過;標記一下回調的auth_token $event->getRequest()->attributes->set('auth_token', $token); } } //這個是 kernel.response事件分發時候調用的 use Symfony\Component\HttpKernel\Event\FilterResponseEvent; public function onKernelResponse(FilterResponseEvent $event) { //檢查是否設置了auth_token if (!$token = $event->getRequest()->attributes->get('auth_token')) { return; } $response = $event->getResponse(); // 建立一個response header放入加密信息; $hash = sha1($response->getContent().$token); $response->headers->set('X-CONTENT-HASH', $hash); }
####註冊監聽者
# app/config/services.yml services: app.tokens.action_listener: class: AppBundle\EventListener\TokenListener arguments: ['%tokens%'] tags: - { name: kernel.event_listener, event: kernel.controller, method: onKernelController } - { name: kernel.event_listener, event: kernel.response, method: onKernelResponse }