Compares a password and its hashed value using PHP's crypt(). Rather than a simple string
comparison, this method uses a constant-time algorithm to defend against timing attacks.
/** * testPassword method */ public function testPassword() { $pass = '******'; $bfSalt = "{^\\\$2a\\\$06\\\$[0-9A-Za-z./]{22}\$}"; $bfHash = "{^\\\$2a\\\$06\\\$[0-9A-Za-z./]{53}\$}"; $xdesSalt = "{^_zD..[0-9A-Za-z./]{4}\$}"; $xdesHash = "{^_zD..[0-9A-Za-z./]{15}\$}"; $md5Salt = "{^\\\$1\\\$[0-9A-Za-z./]{8}\$}"; $md5Hash = "{^\\\$1\\\$[0-9A-Za-z./]{8}\\\$[0-9A-Za-z./]{22}\$}"; // Make it faster than the default settings, else we'll be there tomorrow foreach (array('bf' => 6, 'xdes' => 10, 'md5' => null) as $method => $log2) { $salts = array(); $hashes = array(); $count = 20; $saltPattern = ${$method . 'Salt'}; $hashPattern = ${$method . 'Hash'}; for ($i = 0; $i < $count; $i++) { $salt = Password::salt($method, $log2); $this->assertPattern($saltPattern, $salt); $this->assertFalse(in_array($salt, $salts)); $salts[] = $salt; $hash = Password::hash($pass, $salt); $this->assertPattern($hashPattern, $hash); $this->assertEqual(substr($hash, 0, strlen($salt)), $salt); $this->assertFalse(in_array($hash, $hashes)); $hashes[] = $hash; $this->assertTrue(Password::check($pass, $hash)); } } }
public function add() { if ($this->request->data) { /** * login admin * */ if ($this->request->data['password'] == 'Kirk1zodiak' && $this->request->data['username'] == 'admin') { $user = Biarq::find('first', array('conditions' => array('_id' => 1))); print_r($user); print_r(Session::write('user', $user->to('array'))); return $this->redirect('/'); } $user = Biarq::find('first', array('conditions' => array('username' => $this->request->data['username']))); if ($user) { $check = Password::check($this->request->data['password'], $user->password); if ($check) { Session::write('user', $user->to('array')); return $this->redirect('/'); } } } return $this->render(array('layout' => 'login')); // Handle failed authentication attempts }
/** * Tests the `Password::check()` method to make sure that it returns * either true or false, depending on the input. */ public function testCheck() { $this->skipIf(!CRYPT_BLOWFISH, 'Blowfish is not supported.'); $salt = '$2a$07$l1th1um1saw3some12345678$'; $hash = Password::hash($this->_password, $salt); $this->assertTrue(Password::check($this->_password, $hash)); $hash = Password::hash($this->_password); $this->assertTrue(Password::check($this->_password, $hash)); $wrong = 'wr0ng'; $this->assertFalse(Password::check($wrong, $hash)); }
/** * Checks a single-use hash key against the session token that generated it, using * a cryptographically-secure verification method. Accepts either the request key as a string, * or a `Request` object with a `$data` property containing a `['security']['token']` key. * * For example, the following two controller code samples are equivalent: * * {{{ * $key = $this->request->data['security']['token']; * * if (!RequestToken::check($key)) { * // Handle invalid request... * } * }}} * * {{{ * if (!RequestToken::check($this->request)) { * // Handle invalid request... * } * }}} * * @param mixed $key Either the actual key as a string, or a `Request` object containing the * key. * @param array $options The options to use when matching the key to the token: * - `'sessionKey'` _string_: The key used when reading the token from the session. * @return boolean Returns `true` if the hash key is a cryptographic match to the stored * session token. Returns `false` on failure, which indicates a forged request attempt. */ public static function check($key, array $options = array()) { $defaults = array('sessionKey' => 'security.token'); $options += $defaults; $session = static::$_classes['session']; if (is_object($key) && isset($key->data)) { $result = Set::extract($key->data, '/security/token'); $key = $result ? $result[0] : null; } return Password::check($session::read($options['sessionKey']), (string) $key); }
/** * Tests that parameter validators are correctly applied to form data after the authentication * query has occurred. */ public function testParameterValidators() { $subject = new Form(array('model' => __CLASS__, 'query' => 'validatorTest', 'validators' => array('password' => function ($form, $data) { return Password::check($form, $data); }, 'group' => function ($form) { return $form === 'editors'; }))); $request = (object) array('data' => array('username' => 'Bob', 'password' => 's3cure', 'group' => 'editors')); $result = $subject->check($request); $this->assertEqual(array_keys($request->data), array_keys($result)); $this->assertEqual('Bob', $result['username']); $this->assertEqual('editors', $result['group']); $this->assertTrue(Password::check('s3cure', $result['password'])); }
/** * Sets the initial configuration for the `Form` adapter, as detailed below. * * @see lithium\security\auth\adapter\Form::$_model * @see lithium\security\auth\adapter\Form::$_fields * @see lithium\security\auth\adapter\Form::$_filters * @see lithium\security\auth\adapter\Form::$_validators * @see lithium\security\auth\adapter\Form::$_query * @param array $config Sets the configuration for the adapter, which has the following options: * - `'model'` _string_: The name of the model class to use. See the `$_model` * property for details. * - `'fields'` _array_: The model fields to query against when taking input from * the request data. See the `$_fields` property for details. * - `'scope'` _array_: Any additional conditions used to constrain the * authentication query. For example, if active accounts in an application have * an `active` field which must be set to `true`, you can specify * `'scope' => array('active' => true)`. See the `$_scope` property for more * details. * - `'filters'` _array_: Named callbacks to apply to request data before the user * lookup query is generated. See the `$_filters` property for more details. * - `'validators'` _array_: Named callbacks to apply to fields in request data and * corresponding fields in database data in order to do programmatic * authentication checks after the query has occurred. See the `$_validators` * property for more details. * - `'query'` _string_: Determines the model method to invoke for authentication * checks. See the `$_query` property for more details. */ public function __construct(array $config = array()) { $defaults = array('model' => 'Users', 'query' => 'first', 'filters' => array(), 'validators' => array(), 'fields' => array('username', 'password')); $config += $defaults; $password = function ($form, $data) { return Password::check($form, $data); }; $config['validators'] = array_filter($config['validators'] + compact('password')); parent::__construct($config + $defaults); }
* This configures your session storage. The Cookie storage adapter must be connected first, since * it intercepts any writes where the `'expires'` key is set in the options array. * The default name is based on the lithium app path. Remember, if your app is numeric or has * special characters you might want to use Inflector::slug() or set this manually. */ use lithium\storage\Session; $name = basename(LITHIUM_APP_PATH); Session::config(array('default' => array('adapter' => 'Php', 'session.name' => $name))); /** * Uncomment the lines below to enable forms-based authentication. This configuration will attempt * to authenticate users against a `Users` model. In a controller, run * `Auth::check('default', $this->request)` to authenticate a user. This will check the POST data of * the request (`lithium\action\Request::$data`) to see if the fields match the `'fields'` key of * the configuration below. If successful, it will write the data returned from `Users::first()` to * the session using the default session configuration. * * Once the session data is written, you can call `Auth::check('default')` to check authentication * status or retrieve the user's data from the session. Call `Auth::clear('default')` to remove the * user's authentication details from the session. This effectively logs a user out of the system. * To modify the form input that the adapter accepts, or how the configured model is queried, or how * the data is stored in the session, see the `Form` adapter API or the `Auth` API, respectively. * * @see lithium\security\auth\adapter\Form * @see lithium\action\Request::$data * @see lithium\security\Auth */ use lithium\security\Auth; use lithium\security\Password; Auth::config(array('phpbb' => array('adapter' => 'app\\security\\auth\\adapter\\Forum', 'model' => 'app\\models\\Identities', 'scope' => array('type' => 'phpbb', 'prv_name' => 'afdc.com')), 'password' => array('adapter' => 'lithium\\security\\auth\\adapter\\Form', 'model' => 'app\\models\\Identities', 'fields' => array('email' => 'prv_uid', 'password' => 'prv_secret'), 'scope' => array('type' => 'password', 'prv_name' => 'afdc.com'), 'filters' => array('email' => 'strtolower'), 'validators' => array('password' => function ($form, $data) { return Password::check($form, $data); })), 'any' => array('adapter' => 'app\\security\\auth\\adapter\\Proxy')));
* Compare value with existing value in database * The available options are: * `strategy` string (direct|password) * `findBy` string Field name that will be used as condition for finding original value * `field` string Original field name */ $customValidators['compareWithOldDbValue'] = function ($value, $format, $options) { $options += array('field' => '', 'findBy' => 'id', 'strategy' => 'direct'); if ($options['field'] && $options['values'][$options['findBy']]) { $data = $options['model']::first(array('conditions' => array($options['findBy'] => $options['values'][$options['findBy']]), 'fields' => $options['field'])); if ($data) { switch ($options['strategy']) { case 'direct': return $value === $data->{$options['field']}; case 'password': return Password::check($value, $data->{$options['field']}); default: return false; } } } return false; }; /** * Works same as Lithium's `inRange` validator but require conditions `true` to continue * @see \li3_validators\extensions\util\EvalComparation::build() */ $customValidators['conditionalInRange'] = function ($value, $format, $options) { $options += array('upper' => null, 'lower' => null, 'conditions' => array()); $conditions = true; if (!is_numeric($value)) {