Edited at

Symfony 2.x で CSRF対策

More than 1 year has passed since last update.

どこでハンドリングされるのかは未調査ですが、Form を利用すると設定しておけば自動的に(?)CSRF対策されるそうですが、Form の使い勝手が悪いというか、ある程度テンプレート側に任せたいので token の生成と検証のメソッドを Controller の基底クラスに用意します。

生成した token を hidden で埋め込んで、action で検証という自前実装に使えます…

下記のコードは AppLogger を利用しています。


AppBundle/Controller/AbstractController.php

<?php

namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use AppBundle\DependencyInjection\Logging\AppLogger;

abstract class AbstractController extends Controller {

// Generate token.
protected function generateCsrfToken($tokenType) {
$token = $this->get('security.csrf.token_manager')->refreshToken($tokenType);
if (AppLogger::isDebugEnabled()) {
$name = get_class($this);
$name = substr($name, strrpos($name, '\\') + 1);
$logger->debug('[' . $name . '][CSRF Token][Gen] ' . $tokenType . ' => ' . $token);
}
return $token;
}

// Validate token.
protected function isValidCsrfToken($tokenType, $token) {
// If current is the master, getParentRequest() returns null.
if ($this->get('request_stack')->getParentRequest()) {
// from forward, always valid. (Usualy forward is SUB_REQUEST)
return true;
}
if (AppLogger::isDebugEnabled()) {
$name = get_class($this);
$name = substr($name, strrpos($name, '\\') + 1);
AppLogger::debug('[' . $name . '][CSRF Token][Req] ' . $tokenType . ' => ' . $token);
}
return $this->isCsrfTokenValid($tokenType, $token);
}
}