Skip to content

Commit

Permalink
Adding SecurityComponent::$csrfLimit
Browse files Browse the repository at this point in the history
This property allows you to control the number of tokens
that will be kept active.  Its possible to make really large
CSRF collection sizes.  Capping the number of tokens allows developers
to better control session sizes.
  • Loading branch information
markstory committed Dec 4, 2011
1 parent e421b3b commit 9296f77
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 0 deletions.
17 changes: 17 additions & 0 deletions lib/Cake/Controller/Component/SecurityComponent.php
Expand Up @@ -157,6 +157,19 @@ class SecurityComponent extends Component {
*/
public $csrfUseOnce = true;

/**
* Control the number of tokens a user can keep open.
* This is most useful with one-time use tokens. Since new tokens
* are created on each request, having a hard limit on the number of open tokens
* can be useful in controlling the size of the session file.
*
* When tokens are evicted, the oldest ones will be removed, as they are the most likely
* to be dead/expired.
*
* @var integer
*/
public $csrfLimit = 100;

/**
* Other components used by the Security component
*
Expand Down Expand Up @@ -541,6 +554,10 @@ protected function _validateCsrf($controller) {
*/
protected function _expireTokens($tokens) {
$now = time();
$overflow = count($tokens) - $this->csrfLimit;
if ($overflow > 0) {
$tokens = array_slice($tokens, $overflow + 1, null, true);
}
foreach ($tokens as $nonce => $expires) {
if ($expires < $now) {
unset($tokens[$nonce]);
Expand Down
28 changes: 28 additions & 0 deletions lib/Cake/Test/Case/Controller/Component/SecurityComponentTest.php
Expand Up @@ -1288,5 +1288,33 @@ public function testGenerateToken() {
$this->Security->generateToken($request);

$this->assertNotEmpty($request->params['_Token']);
$this->assertTrue(isset($request->params['_Token']['unlockedFields']));
$this->assertTrue(isset($request->params['_Token']['key']));
}

/**
* Test the limiting of CSRF tokens.
*
* @return void
*/
public function testCsrfLimit() {
$this->Security->csrfLimit = 3;
$time = strtotime('+10 minutes');
$tokens = array(
'1' => $time,
'2' => $time,
'3' => $time,
'4' => $time,
'5' => $time,
);
$this->Security->Session->write('_Token', array('csrfTokens' => $tokens));
$this->Security->generateToken($this->Controller->request);
$result = $this->Security->Session->read('_Token.csrfTokens');

$this->assertFalse(isset($result['1']));
$this->assertFalse(isset($result['2']));
$this->assertFalse(isset($result['3']));
$this->assertTrue(isset($result['4']));
$this->assertTrue(isset($result['5']));
}
}

0 comments on commit 9296f77

Please sign in to comment.