forked from thomheymann/Attempt-Component
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
265d078
commit 97f2846
Showing
1 changed file
with
81 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
Attempt Component | ||
================= | ||
|
||
A simple component to protect sensitive actions from brute force attacks. | ||
|
||
|
||
API | ||
--- | ||
|
||
### count($action) | ||
Returns the number of failed attempts for a certain action. | ||
|
||
### limit($action, $limit = 5) | ||
Returns false if the number of failed attempts is bigger than the passed limit. | ||
|
||
### fail($action, $duration = '+10 minutes') | ||
Creates a failed attempt that counts towards the limit for the passed duration | ||
|
||
### reset($action) | ||
Deletes all failed attempts for a certain action | ||
|
||
### cleanup() | ||
Deletes all expired failed attempts from the database. This should be run via CakeShell every now and then. | ||
|
||
|
||
Schema | ||
------ | ||
|
||
CREATE TABLE `attempts` ( | ||
`id` char(36) NOT NULL DEFAULT '', | ||
`ip` varchar(64) DEFAULT NULL, | ||
`action` varchar(32) DEFAULT NULL, | ||
`created` datetime DEFAULT NULL, | ||
`expires` datetime DEFAULT NULL, | ||
PRIMARY KEY (`id`), | ||
KEY `ip` (`ip`,`action`), | ||
KEY `expires` (`expires`) | ||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 | ||
|
||
|
||
Example Implementation | ||
---------------------- | ||
|
||
class ExampleController extends Controller { | ||
|
||
var $components = array( | ||
'Attempt' | ||
); | ||
|
||
var $loginAttemptLimit = 10; | ||
var $loginAttemptDuration = '+1 hour'; | ||
|
||
public function login() { | ||
// Form submitted? | ||
if ( $formSubmitted = true ) { | ||
// All required fields entered? | ||
if ( $validFormData = true ) { | ||
// Limit to 10 failed attempts | ||
if ( $this->Attempt->limit('login', $this->loginAttemptLimit) ) { | ||
// Validate user credentials | ||
if ( $validCredentials = true ) { | ||
// Log user in | ||
} else { | ||
// Invalid credentials, count as failed attempt for an hour | ||
$this->Attempt->fail('login', $this->loginAttemptDuration); | ||
$this->Session->setFlash('Unknown user or wrong password'); | ||
} | ||
} else { | ||
// User exceeded attempt limit | ||
// Ideally show a CAPTCHA (ensuring this is not a robot | ||
// without blocking out and frustrating users), | ||
// otherwise show error message | ||
$this->Session->setFlash('Too many failed attempts!'); | ||
} | ||
} else { | ||
// Invalid form data but keep it ambiguous | ||
$this->Session->setFlash('Unknown user or wrong password'); | ||
} | ||
} | ||
} | ||
} |