Skip to content
Browse files

[Security] Added CSRF sub-component

  • Loading branch information...
1 parent e24dbf7 commit 1bf16400fbc10c2aaecfa1120e8c1a58157ef368 @webmozart webmozart committed
View
1 composer.json
@@ -52,6 +52,7 @@
"symfony/security": "self.version",
"symfony/security-acl": "self.version",
"symfony/security-core": "self.version",
+ "symfony/security-csrf": "self.version",
"symfony/security-http": "self.version",
"symfony/security-bundle": "self.version",
"symfony/serializer": "self.version",
View
3 src/Symfony/Component/Security/Csrf/.gitignore
@@ -0,0 +1,3 @@
+vendor/
+composer.lock
+phpunit.xml
View
105 src/Symfony/Component/Security/Csrf/CsrfTokenGenerator.php
@@ -0,0 +1,105 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Security\Csrf;
+
+use Symfony\Component\Security\Core\Util\SecureRandomInterface;
+use Symfony\Component\Security\Core\Util\SecureRandom;
+use Symfony\Component\Security\Core\Util\StringUtils;
+use Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage;
+use Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface;
+
+/**
+ * Generates and validates CSRF tokens.
+ *
+ * @since 2.4
+ * @author Bernhard Schussek <bernhard.schussek@symfony.com>
+ */
+class CsrfTokenGenerator implements CsrfTokenGeneratorInterface
+{
+ /**
+ * The entropy of the token in bits.
+ * @var integer
+ */
+ const TOKEN_ENTROPY = 256;
+
+ /**
+ * @var TokenStorageInterface
+ */
+ private $storage;
+
+ /**
+ * The generator for random values.
+ * @var SecureRandomInterface
+ */
+ private $random;
+
+ /**
+ * Creates a new CSRF provider using PHP's native session storage.
+ *
+ * @param TokenStorageInterface $storage The storage for storing generated
+ * CSRF tokens
+ * @param SecureRandomInterface $random The used random value generator
+ * @param integer $entropy The amount of entropy collected for
+ * newly generated tokens (in bits)
+ *
+ */
+ public function __construct(TokenStorageInterface $storage = null, SecureRandomInterface $random = null, $entropy = self::TOKEN_ENTROPY)
+ {
+ if (null === $storage) {
+ $storage = new NativeSessionTokenStorage();
+ }
+
+ if (null === $random) {
+ $random = new SecureRandom();
+ }
+
+ $this->storage = $storage;
+ $this->random = $random;
+ $this->entropy = $entropy;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function generateCsrfToken($tokenId)
+ {
+ $currentToken = $this->storage->getToken($tokenId, false);
+
+ // Token exists and is still valid
+ if (false !== $currentToken) {
+ return $currentToken;
+ }
+
+ // Token needs to be (re)generated
+ // Generate an URI safe base64 encoded string that does not contain "+",
+ // "/" or "=" which need to be URL encoded and make URLs unnecessarily
+ // longer.
+ $bytes = $this->random->nextBytes($this->entropy / 8);
+ $token = rtrim(strtr(base64_encode($bytes), '+/', '-_'), '=');
+
+ $this->storage->setToken($tokenId, $token);
+
+ return $token;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function isCsrfTokenValid($tokenId, $token)
+ {
+ if (!$this->storage->hasToken($tokenId)) {
+ return false;
+ }
+
+ return StringUtils::equals((string) $this->storage->getToken($tokenId), $token);
+ }
+}
View
50 src/Symfony/Component/Security/Csrf/CsrfTokenGeneratorInterface.php
@@ -0,0 +1,50 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Security\Csrf;
+
+/**
+ * Generates and validates CSRF tokens.
+ *
+ * You can generate a CSRF token by using the method {@link generateCsrfToken()}.
+ * This method expects a unique token ID as argument. The token ID can later be
+ * used to validate a token provided by the user.
+ *
+ * Token IDs do not necessarily have to be secret, but they should NEVER be
+ * created from data provided by the client. A good practice is to hard-code the
+ * token IDs for the various CSRF tokens used by your application.
+ *
+ * You should use the method {@link isCsrfTokenValid()} to check a CSRF token
+ * submitted by the client. This method will return true if the CSRF token is
+ * valid.
+ *
+ * @since 2.4
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+interface CsrfTokenGeneratorInterface
+{
+ /**
+ * Generates a CSRF token with the given token ID.
+ *
+ * @param string $tokenId An ID that identifies the token
+ */
+ public function generateCsrfToken($tokenId);
+
+ /**
+ * Validates a CSRF token.
+ *
+ * @param string $tokenId The token ID used when generating the token
+ * @param string $token The token supplied by the client
+ *
+ * @return Boolean Whether the token supplied by the client is correct
+ */
+ public function isCsrfTokenValid($tokenId, $token);
+}
View
19 src/Symfony/Component/Security/Csrf/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2004-2013 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
View
21 src/Symfony/Component/Security/Csrf/README.md
@@ -0,0 +1,21 @@
+Security Component - CSRF
+=========================
+
+The Security CSRF (cross-site request forgery) component provides a class
+`CsrfTokenGenerator` for generating and validating CSRF tokens.
+
+Resources
+---------
+
+Documentation:
+
+http://symfony.com/doc/2.4/book/security.html
+
+Tests
+-----
+
+You can run the unit tests with the following command:
+
+ $ cd path/to/Symfony/Component/Security/Csrf/
+ $ composer.phar install --dev
+ $ phpunit
View
148 src/Symfony/Component/Security/Csrf/Tests/CsrfTokenGeneratorTest.php
@@ -0,0 +1,148 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Form\Tests\Extension\Csrf\CsrfProvider;
+
+use Symfony\Component\Security\Csrf\CsrfTokenGenerator;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class CsrfTokenGeneratorTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * A non alpha-numeric byte string
+ * @var string
+ */
+ private static $bytes;
+
+ /**
+ * @var \PHPUnit_Framework_MockObject_MockObject
+ */
+ private $random;
+
+ /**
+ * @var \PHPUnit_Framework_MockObject_MockObject
+ */
+ private $storage;
+
+ /**
+ * @var CsrfTokenGenerator
+ */
+ private $generator;
+
+ public static function setUpBeforeClass()
+ {
+ self::$bytes = base64_decode('aMf+Tct/RLn2WQ==');
+ }
+
+ protected function setUp()
+ {
+ $this->random = $this->getMock('Symfony\Component\Security\Core\Util\SecureRandomInterface');
+ $this->storage = $this->getMock('Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface');
+ $this->generator = new CsrfTokenGenerator($this->storage, $this->random);
+ }
+
+ protected function tearDown()
+ {
+ $this->random = null;
+ $this->storage = null;
+ $this->generator = null;
+ }
+
+ public function testGenerateNewToken()
+ {
+ $this->storage->expects($this->once())
+ ->method('getToken')
+ ->with('token_id', false)
+ ->will($this->returnValue(false));
+
+ $this->storage->expects($this->once())
+ ->method('setToken')
+ ->with('token_id', $this->anything())
+ ->will($this->returnCallback(function ($tokenId, $token) use (&$storedToken) {
+ $storedToken = $token;
+ }));
+
+ $this->random->expects($this->once())
+ ->method('nextBytes')
+ ->will($this->returnValue(self::$bytes));
+
+ $token = $this->generator->generateCsrfToken('token_id');
+
+ $this->assertSame($token, $storedToken);
+ $this->assertTrue(ctype_print($token), 'is printable');
+ $this->assertStringNotMatchesFormat('%S+%S', $token, 'is URI safe');
+ $this->assertStringNotMatchesFormat('%S/%S', $token, 'is URI safe');
+ $this->assertStringNotMatchesFormat('%S=%S', $token, 'is URI safe');
+ }
+
+ public function testUseExistingTokenIfAvailable()
+ {
+ $this->storage->expects($this->once())
+ ->method('getToken')
+ ->with('token_id', false)
+ ->will($this->returnValue('TOKEN'));
+
+ $this->storage->expects($this->never())
+ ->method('setToken');
+
+ $this->random->expects($this->never())
+ ->method('nextBytes');
+
+ $token = $this->generator->generateCsrfToken('token_id');
+
+ $this->assertEquals('TOKEN', $token);
+ }
+
+ public function testMatchingTokenIsValid()
+ {
+ $this->storage->expects($this->once())
+ ->method('hasToken')
+ ->with('token_id')
+ ->will($this->returnValue(true));
+
+ $this->storage->expects($this->once())
+ ->method('getToken')
+ ->with('token_id')
+ ->will($this->returnValue('TOKEN'));
+
+ $this->assertTrue($this->generator->isCsrfTokenValid('token_id', 'TOKEN'));
+ }
+
+ public function testNonMatchingTokenIsNotValid()
+ {
+ $this->storage->expects($this->once())
+ ->method('hasToken')
+ ->with('token_id')
+ ->will($this->returnValue(true));
+
+ $this->storage->expects($this->once())
+ ->method('getToken')
+ ->with('token_id')
+ ->will($this->returnValue('TOKEN'));
+
+ $this->assertFalse($this->generator->isCsrfTokenValid('token_id', 'FOOBAR'));
+ }
+
+ public function testNonExistingTokenIsNotValid()
+ {
+ $this->storage->expects($this->once())
+ ->method('hasToken')
+ ->with('token_id')
+ ->will($this->returnValue(false));
+
+ $this->storage->expects($this->never())
+ ->method('getToken');
+
+ $this->assertFalse($this->generator->isCsrfTokenValid('token_id', 'FOOBAR'));
+ }
+}
View
99 src/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php
@@ -0,0 +1,99 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Form\Tests\Extension\Csrf\CsrfProvider;
+
+use Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @runTestsInSeparateProcesses
+ */
+class NativeSessionTokenStorageTest extends \PHPUnit_Framework_TestCase
+{
+ const SESSION_NAMESPACE = 'foobar';
+
+ /**
+ * @var NativeSessionTokenStorage
+ */
+ private $storage;
+
+ public static function setUpBeforeClass()
+ {
+ ini_set('session.save_handler', 'files');
+ ini_set('session.save_path', sys_get_temp_dir());
+
+ parent::setUpBeforeClass();
+ }
+
+ protected function setUp()
+ {
+ $_SESSION = array();
+
+ $this->storage = new NativeSessionTokenStorage(self::SESSION_NAMESPACE);
+ }
+
+ public function testStoreTokenInClosedSession()
+ {
+ $this->storage->setToken('token_id', 'TOKEN');
+
+ $this->assertSame(array(self::SESSION_NAMESPACE => array('token_id' => 'TOKEN')), $_SESSION);
+ }
+
+ public function testStoreTokenInClosedSessionWithExistingSessionId()
+ {
+ session_id('foobar');
+
+ $this->assertSame(PHP_SESSION_NONE, session_status());
+
+ $this->storage->setToken('token_id', 'TOKEN');
+
+ $this->assertSame(PHP_SESSION_ACTIVE, session_status());
+ $this->assertSame(array(self::SESSION_NAMESPACE => array('token_id' => 'TOKEN')), $_SESSION);
+ }
+
+ public function testStoreTokenInActiveSession()
+ {
+ session_start();
+
+ $this->storage->setToken('token_id', 'TOKEN');
+
+ $this->assertSame(array(self::SESSION_NAMESPACE => array('token_id' => 'TOKEN')), $_SESSION);
+ }
+
+ /**
+ * @depends testStoreTokenInClosedSession
+ */
+ public function testCheckToken()
+ {
+ $this->assertFalse($this->storage->hasToken('token_id'));
+
+ $this->storage->setToken('token_id', 'TOKEN');
+
+ $this->assertTrue($this->storage->hasToken('token_id'));
+ }
+
+ /**
+ * @depends testStoreTokenInClosedSession
+ */
+ public function testGetExistingToken()
+ {
+ $this->storage->setToken('token_id', 'TOKEN');
+
+ $this->assertSame('TOKEN', $this->storage->getToken('token_id'));
+ }
+
+ public function testGetNonExistingToken()
+ {
+ $this->assertSame('DEFAULT', $this->storage->getToken('token_id', 'DEFAULT'));
+ }
+}
View
144 src/Symfony/Component/Security/Csrf/Tests/TokenStorage/SessionTokenStorageTest.php
@@ -0,0 +1,144 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Form\Tests\Extension\Csrf\CsrfProvider;
+
+use Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage;
+
+/**
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class SessionTokenStorageTest extends \PHPUnit_Framework_TestCase
+{
+ const SESSION_NAMESPACE = 'foobar';
+
+ /**
+ * @var \PHPUnit_Framework_MockObject_MockObject
+ */
+ private $session;
+
+ /**
+ * @var SessionTokenStorage
+ */
+ private $storage;
+
+ protected function setUp()
+ {
+ if (!class_exists('Symfony\Component\HttpFoundation\Session\SessionInterface')) {
+ $this->markTestSkipped('The "HttpFoundation" component is not available');
+ }
+
+ $this->session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->storage = new SessionTokenStorage($this->session, self::SESSION_NAMESPACE);
+ }
+
+ public function testStoreTokenInClosedSession()
+ {
+ $this->session->expects($this->any())
+ ->method('isStarted')
+ ->will($this->returnValue(false));
+
+ $this->session->expects($this->once())
+ ->method('start');
+
+ $this->session->expects($this->once())
+ ->method('set')
+ ->with(self::SESSION_NAMESPACE.'/token_id', 'TOKEN');
+
+ $this->storage->setToken('token_id', 'TOKEN');
+ }
+
+ public function testStoreTokenInActiveSession()
+ {
+ $this->session->expects($this->any())
+ ->method('isStarted')
+ ->will($this->returnValue(true));
+
+ $this->session->expects($this->never())
+ ->method('start');
+
+ $this->session->expects($this->once())
+ ->method('set')
+ ->with(self::SESSION_NAMESPACE.'/token_id', 'TOKEN');
+
+ $this->storage->setToken('token_id', 'TOKEN');
+ }
+
+ public function testCheckTokenInClosedSession()
+ {
+ $this->session->expects($this->any())
+ ->method('isStarted')
+ ->will($this->returnValue(false));
+
+ $this->session->expects($this->once())
+ ->method('start');
+
+ $this->session->expects($this->once())
+ ->method('has')
+ ->with(self::SESSION_NAMESPACE.'/token_id')
+ ->will($this->returnValue('RESULT'));
+
+ $this->assertSame('RESULT', $this->storage->hasToken('token_id'));
+ }
+
+ public function testCheckTokenInActiveSession()
+ {
+ $this->session->expects($this->any())
+ ->method('isStarted')
+ ->will($this->returnValue(true));
+
+ $this->session->expects($this->never())
+ ->method('start');
+
+ $this->session->expects($this->once())
+ ->method('has')
+ ->with(self::SESSION_NAMESPACE.'/token_id')
+ ->will($this->returnValue('RESULT'));
+
+ $this->assertSame('RESULT', $this->storage->hasToken('token_id'));
+ }
+
+ public function testGetTokenFromClosedSession()
+ {
+ $this->session->expects($this->any())
+ ->method('isStarted')
+ ->will($this->returnValue(false));
+
+ $this->session->expects($this->once())
+ ->method('start');
+
+ $this->session->expects($this->once())
+ ->method('get')
+ ->with(self::SESSION_NAMESPACE.'/token_id', 'DEFAULT')
+ ->will($this->returnValue('RESULT'));
+
+ $this->assertSame('RESULT', $this->storage->getToken('token_id', 'DEFAULT'));
+ }
+
+ public function testGetTokenFromActiveSession()
+ {
+ $this->session->expects($this->any())
+ ->method('isStarted')
+ ->will($this->returnValue(true));
+
+ $this->session->expects($this->never())
+ ->method('start');
+
+ $this->session->expects($this->once())
+ ->method('get')
+ ->with(self::SESSION_NAMESPACE.'/token_id', 'DEFAULT')
+ ->will($this->returnValue('RESULT'));
+
+ $this->assertSame('RESULT', $this->storage->getToken('token_id', 'DEFAULT'));
+ }
+}
View
101 src/Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.php
@@ -0,0 +1,101 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Security\Csrf\TokenStorage;
+
+/**
+ * Token storage that uses PHP's native session handling.
+ *
+ * @since 2.4
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class NativeSessionTokenStorage implements TokenStorageInterface
+{
+ /**
+ * The namespace used to store values in the session.
+ * @var string
+ */
+ const SESSION_NAMESPACE = '_csrf';
+
+ /**
+ * @var Boolean
+ */
+ private $sessionStarted = false;
+
+ /**
+ * @var string
+ */
+ private $namespace;
+
+ /**
+ * Initializes the storage with a session namespace.
+ *
+ * @param string $namespace The namespace under which the token is stored
+ * in the session
+ */
+ public function __construct($namespace = self::SESSION_NAMESPACE)
+ {
+ $this->namespace = $namespace;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getToken($tokenId, $default = null)
+ {
+ if (!$this->sessionStarted) {
+ $this->startSession();
+ }
+
+ if (isset($_SESSION[$this->namespace][$tokenId])) {
+ return $_SESSION[$this->namespace][$tokenId];
+ }
+
+ return $default;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setToken($tokenId, $token)
+ {
+ if (!$this->sessionStarted) {
+ $this->startSession();
+ }
+
+ $_SESSION[$this->namespace][$tokenId] = $token;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function hasToken($tokenId)
+ {
+ if (!$this->sessionStarted) {
+ $this->startSession();
+ }
+
+ return isset($_SESSION[$this->namespace][$tokenId]);
+ }
+
+ private function startSession()
+ {
+ if (version_compare(PHP_VERSION, '5.4', '>=')) {
+ if (PHP_SESSION_NONE === session_status()) {
+ session_start();
+ }
+ } elseif (!session_id()) {
+ session_start();
+ }
+
+ $this->sessionStarted = true;
+ }
+}
View
89 src/Symfony/Component/Security/Csrf/TokenStorage/SessionTokenStorage.php
@@ -0,0 +1,89 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Security\Csrf\TokenStorage;
+
+use Symfony\Component\HttpFoundation\Session\SessionInterface;
+
+/**
+ * Token storage that uses a Symfony2 Session object.
+ *
+ * @since 2.4
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class SessionTokenStorage implements TokenStorageInterface
+{
+ /**
+ * The namespace used to store values in the session.
+ * @var string
+ */
+ const SESSION_NAMESPACE = '_csrf';
+
+ /**
+ * The user session from which the session ID is returned
+ * @var SessionInterface
+ */
+ private $session;
+
+ /**
+ * @var string
+ */
+ private $namespace;
+
+ /**
+ * Initializes the storage with a Session object and a session namespace.
+ *
+ * @param SessionInterface $session The user session
+ * @param string $namespace The namespace under which the token
+ * is stored in the session
+ */
+ public function __construct(SessionInterface $session, $namespace = self::SESSION_NAMESPACE)
+ {
+ $this->session = $session;
+ $this->namespace = $namespace;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getToken($tokenId, $default = null)
+ {
+ if (!$this->session->isStarted()) {
+ $this->session->start();
+ }
+
+ return $this->session->get($this->namespace . '/' . $tokenId, $default);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setToken($tokenId, $token)
+ {
+ if (!$this->session->isStarted()) {
+ $this->session->start();
+ }
+
+ $this->session->set($this->namespace . '/' . $tokenId, $token);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function hasToken($tokenId)
+ {
+ if (!$this->session->isStarted()) {
+ $this->session->start();
+ }
+
+ return $this->session->has($this->namespace . '/' . $tokenId);
+ }
+}
View
49 src/Symfony/Component/Security/Csrf/TokenStorage/TokenStorageInterface.php
@@ -0,0 +1,49 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Security\Csrf\TokenStorage;
+
+/**
+ * Stores CSRF tokens.
+ *
+ * @since 2.4
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+interface TokenStorageInterface
+{
+ /**
+ * Reads a stored CSRF token.
+ *
+ * @param string $tokenId The token ID
+ * @param mixed $default The value to be returned if no token is set
+ *
+ * @return mixed The stored token or the default value, if no token is set
+ */
+ public function getToken($tokenId, $default = null);
+
+ /**
+ * Stores a CSRF token.
+ *
+ * @param string $tokenId The token ID
+ * @param mixed $token The CSRF token
+ */
+ public function setToken($tokenId, $token);
+
+ /**
+ * Checks whether a token with the given token ID exists.
+ *
+ * @param string $tokenId The token ID
+ *
+ * @return Boolean Returns true if a token is stored for the given token ID,
+ * false otherwise.
+ */
+ public function hasToken($tokenId);
+}
View
34 src/Symfony/Component/Security/Csrf/composer.json
@@ -0,0 +1,34 @@
+{
+ "name": "symfony/security-csrf",
+ "type": "library",
+ "description": "Symfony Security Component - CSRF Library",
+ "keywords": [],
+ "homepage": "http://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "symfony/security-core": "~2.4"
+ },
+ "autoload": {
+ "psr-0": { "Symfony\\Component\\Security\\Csrf\\": "" }
+ },
+ "target-dir": "Symfony/Component/Security/Csrf",
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.4-dev"
+ }
+ }
+}
View
29 src/Symfony/Component/Security/Csrf/phpunit.xml.dist
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit backupGlobals="false"
+ backupStaticAttributes="false"
+ colors="true"
+ convertErrorsToExceptions="true"
+ convertNoticesToExceptions="true"
+ convertWarningsToExceptions="true"
+ processIsolation="false"
+ stopOnFailure="false"
+ syntaxCheck="false"
+ bootstrap="vendor/autoload.php"
+>
+ <testsuites>
+ <testsuite name="Symfony Security Component CSRF Test Suite">
+ <directory>./Tests/</directory>
+ </testsuite>
+ </testsuites>
+
+ <filter>
+ <whitelist>
+ <directory>./</directory>
+ <exclude>
+ <directory>./vendor</directory>
+ <directory>./Tests</directory>
+ </exclude>
+ </whitelist>
+ </filter>
+</phpunit>
View
1 src/Symfony/Component/Security/composer.json
@@ -24,6 +24,7 @@
"replace": {
"symfony/security-acl": "self.version",
"symfony/security-core": "self.version",
+ "symfony/security-csrf": "self.version",
"symfony/security-http": "self.version"
},
"require-dev": {

0 comments on commit 1bf1640

Please sign in to comment.
Something went wrong with that request. Please try again.