Adding support for nonce expiry.

Adding simple time based nonce expiration. This does a simple cleanup on
each request, to remove stale tokens.  Tests added.
This commit is contained in:
mark_story 2010-10-02 00:20:58 -04:00
parent 711e736cd3
commit a10f1478ee
2 changed files with 37 additions and 0 deletions

View file

@ -705,6 +705,7 @@ class SecurityComponent extends Component {
} }
if (!empty($tokenData['csrfTokens'])) { if (!empty($tokenData['csrfTokens'])) {
$token['csrfTokens'] += $tokenData['csrfTokens']; $token['csrfTokens'] += $tokenData['csrfTokens'];
$token['csrfTokens'] = $this->_expireTokens($token['csrfTokens']);
} }
} }
$controller->request->params['_Token'] = $token; $controller->request->params['_Token'] = $token;
@ -729,6 +730,23 @@ class SecurityComponent extends Component {
return false; return false;
} }
/**
* Expire CSRF nonces and remove them from the valid tokens.
* Uses a simple timeout to expire the tokens.
*
* @param array $tokens An array of nonce => expires.
* @return An array of nonce => expires.
*/
protected function _expireTokens($tokens) {
$tokenExpiryTime = strtotime($this->csrfExpires);
foreach ($tokens as $nonce => $expires) {
if ($expires < $tokenExpiryTime) {
unset($tokens[$nonce]);
}
}
return $tokens;
}
/** /**
* Sets the default login options for an HTTP-authenticated request * Sets the default login options for an HTTP-authenticated request
* *

View file

@ -1296,4 +1296,23 @@ DIGEST;
$token = $this->Security->Session->read('_Token'); $token = $this->Security->Session->read('_Token');
$this->assertFalse(isset($token['csrfTokens']['nonce1']), 'Token was not consumed'); $this->assertFalse(isset($token['csrfTokens']['nonce1']), 'Token was not consumed');
} }
/**
* test that expired values in the csrfTokens are cleaned up.
*
* @return void
*/
function testCsrfNonceVacuum() {
$this->Security->validatePost = false;
$this->Security->csrfCheck = true;
$this->Security->csrfExpires = '+10 minutes';
$this->Security->Session->write('_Token.csrfTokens', array(
'poof' => strtotime('-11 minutes'),
'dust' => strtotime('-20 minutes')
));
$this->Security->startup($this->Controller);
$tokens = $this->Security->Session->read('_Token.csrfTokens');
$this->assertEquals(1, count($tokens), 'Too many tokens left behind');
}
} }