예제 #1
0
 public function generatePassword($entity)
 {
     $newPassword = substr(md5(rand() . rand()), 0, 8);
     $entity->prv_secret = Password::hash($newPassword);
     Logger::debug("New Password for " . $entity->prv_uid . ": {$newPassword} (hash: {$entity->prv_secret})");
     return $newPassword;
 }
 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
 }
예제 #3
0
 public static function find($type = 'all', array $options = array())
 {
     $result = array();
     $users = array(array('id' => 1, 'username' => 'user1', 'email' => '*****@*****.**', 'password' => Password::hash('user1')), array('id' => 2, 'username' => 'user2', 'email' => '*****@*****.**', 'password' => Password::hash('user2')), array('id' => 3, 'username' => 'user3', 'email' => '*****@*****.**', 'password' => Password::hash('user3')));
     switch ($type) {
         case 'first':
             if ($options['conditions']) {
                 $conditions = '';
                 foreach ($options['conditions'] as $key => $condition) {
                     !$conditions || ($conditions .= ' && ');
                     $comparation = '==';
                     if (is_array($condition)) {
                         $keys = array_keys($condition);
                         $comparation = $keys[0];
                         $condition = $condition[$keys[0]];
                     }
                     $conditions .= "\$user['{$key}'] {$comparation} '{$condition}'";
                 }
                 $eval = "return ({$conditions});";
                 foreach ($users as $user) {
                     if (eval($eval)) {
                         $result[] = $user;
                     }
                 }
                 if ($result) {
                     return new Record(array('data' => $result[0], 'model' => __CLASS__));
                 }
                 return null;
             }
             return new Record(array('data' => $users[0], 'model' => __CLASS__));
         case 'all':
         default:
             return new Record(array('data' => $users, 'model' => __CLASS__));
     }
 }
예제 #4
0
 /**
  * testPasswordMaxLength method
  */
 public function testPasswordMaxLength()
 {
     foreach (array('bf' => 72) as $method => $length) {
         $salt = Password::salt($method);
         $pass = str_repeat('a', $length);
         $this->assertIdentical(Password::hash($pass, $salt), Password::hash($pass . 'a', $salt));
     }
 }
 /**
  * Tests that a random sequence of keys and tokens properly match one another.
  */
 public function testKeyMatching()
 {
     for ($i = 0; $i < 4; $i++) {
         $token = RequestToken::get(array('regenerate' => true));
         for ($j = 0; $j < 4; $j++) {
             $key = Password::hash($token);
             $this->assertTrue(RequestToken::check($key));
         }
     }
 }
예제 #6
0
 public function testConfirm()
 {
     $validate = Validator::check(array('password' => 'user5', 'confirm_password' => 'user5'), array('confirm_password' => array('confirm', 'message' => 'Please confirm your password!')));
     $this->assertTrue(empty($validate));
     $validate = Validator::check(array('password' => 'user5', 'confirm_password' => 'user4'), array('confirm_password' => array('confirm', 'message' => 'Please confirm your password!')));
     $this->assertTrue(!empty($validate));
     $validate = Validator::check(array('password' => Password::hash('user5'), 'confirm_password' => 'user5'), array('confirm_password' => array('confirm', 'message' => 'Please confirm your password!', 'strategy' => 'password')));
     $this->assertTrue(empty($validate));
     $validate = Validator::check(array('password' => Password::hash('user5'), 'confirm_password' => 'user4'), array('confirm_password' => array('confirm', 'message' => 'Please confirm your password!', 'strategy' => 'password')));
     $this->assertTrue(!empty($validate));
     $validate = Validator::check(array('original_password' => 'user5', 'confirm_password' => 'user5'), array('confirm_password' => array('confirm', 'message' => 'Please confirm your password!', 'against' => 'original_password')));
     $this->assertTrue(empty($validate));
     $validate = Validator::check(array('original_password' => 'user5', 'confirm_password' => 'user4'), array('confirm_password' => array('confirm', 'message' => 'Please confirm your password!', 'against' => 'original_password')));
     $this->assertTrue(!empty($validate));
 }
예제 #7
0
 /**
  * Apply proper password hashing (on create or change password)
  * On create:
  * 	- apply defined default user group (LI3_UM_DefaultUserGroup)
  * 	- apply defined active status (LI3_UM_RequireUserActivation)
  * 	  0 - require user to activate account trough generated link with token
  *    1 - don't require further actions, account is already activated
  */
 public static function __init()
 {
     static::applyFilter('save', function ($self, $params, $chain) {
         if ($params['data']) {
             $params['entity']->set($params['data']);
             $params['data'] = array();
         }
         if (!$params['entity']->exists()) {
             if ($params['entity']->password) {
                 $params['entity']->password = Password::hash($params['entity']->password);
             }
             $params['entity']->active = 1;
             if (LI3_UM_RequireUserActivation && $self::$request) {
                 $params['entity']->active = 0;
             }
             $params['entity']->user_group_id = LI3_UM_DefaultUserGroup;
         } else {
             if ($params['entity']->password && $params['entity']->modified('password')) {
                 $params['entity']->password = Password::hash($params['entity']->password);
             }
         }
         return $chain->next($self, $params, $chain);
     });
     static::applyFilter('save', function ($self, $params, $chain) {
         if (($save = $chain->next($self, $params, $chain)) && $params['options']['events'] === 'create') {
             $user = $params['entity'];
             AboutUsers::create(array('user_id' => $user->id))->save();
             if (LI3_UM_RequireUserActivation && $self::$request) {
                 $token = Token::generate($user->email);
                 UserActivations::create(array('user_id' => $user->id, 'token' => $token))->save();
                 $link = Router::match(array('li3_usermanager.Users::activate', 'id' => $user->id, 'token' => $token), $self::$request, array('absolute' => true));
                 Mailer::$_data['subject'] = 'Your activation link!';
                 Mailer::$_data['from'] = LI3_UM_ActivationEmailFrom;
                 Mailer::$_data['to'] = $user->email;
                 Mailer::$_data['body'] = 'This is your activation link:' . "\n" . $link;
             }
         }
         return $save;
     });
 }
예제 #8
0
 /**
  * Tests salting passwords with the MD5 algorithm.
  */
 public function testSaltMD5()
 {
     $this->skipIf(!CRYPT_MD5, 'MD5 is not supported.');
     $saltPattern = "{^\\\$1\\\$[0-9A-Za-z./]{8}\$}";
     $hashPattern = "{^\\\$1\\\$[0-9A-Za-z./]{8}\\\$[0-9A-Za-z./]{22}\$}";
     $salt = Password::salt('md5', null);
     $this->assertPattern($saltPattern, $salt);
     $this->assertNotEqual($salt, Password::salt('md5', null));
     $hash = Password::hash($this->_password, $salt);
     $hash2 = Password::hash($this->_password, Password::salt('md5', null));
     $this->assertPattern($hashPattern, $hash);
     $this->assertNotEqual($hash, $hash2);
 }
예제 #9
0
 /**
  * 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);
 }
예제 #10
0
 /**
  * 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']));
 }
예제 #11
0
<?php

use app\models\Users;
use lithium\security\Password;
Users::applyFilter('save', function ($self, $params, $chain) {
    if ($params['data']) {
        $params['entity']->set($params['data']);
        $params['data'] = array();
    }
    if (!$params['entity']->exists()) {
        $params['entity']->password = Password::hash($params['entity']->password);
    }
    return $chain->next($self, $params, $chain);
});
예제 #12
0
파일: Form.php 프로젝트: nashadalam/lithium
 /**
  * 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);
 }
예제 #13
0
 public static function __init()
 {
     /*
      * Some special validation rules
      */
     Validator::add('uniqueEmail', function ($value) {
         $current_user = Auth::check('li3b_user');
         if (!empty($current_user)) {
             $user = User::find('first', array('fields' => array('_id'), 'conditions' => array('email' => $value, '_id' => array('$ne' => new MongoId($current_user['_id'])))));
         } else {
             $user = User::find('first', array('fields' => array('_id'), 'conditions' => array('email' => $value)));
         }
         if (!empty($user)) {
             return false;
         }
         return true;
     });
     Validator::add('notEmptyHash', function ($value) {
         if ($value == Password::hash('')) {
             return false;
         }
         return true;
     });
     Validator::add('moreThanFive', function ($value) {
         if (strlen($value) < 5) {
             return false;
         }
         return true;
     });
     Validator::add('notTooLarge', function ($value) {
         if ($value == 'TOO_LARGE.jpg') {
             return false;
         }
         return true;
     });
     Validator::add('invalidFileType', function ($value) {
         if ($value == 'INVALID_FILE_TYPE.jpg') {
             return false;
         }
         return true;
     });
     parent::__init();
     /*
      * If told to ues a specific connection, do so.
      * Otherwise, use the default li3b_users connection.
      * Note: This model requires MongoDB.
      * Also note: This must be called AFTER parent::__init()
      *
      * This is useful if the main application also uses MongoDB
      * and wishes everything to use the same database...Be it
      * local or on something like MongoLab or wherever.
      *
      * In fact, when gluing together libraries, one may choose
      * all libraries that use the same database and kinda go
      * with each other. That way it'll end up looking like a single
      * cohesive application from the database's point of view.
      * Of course the it's difficult to avoid conflicts in the MongoDB
      * collection names. In this case, this model is prefixing the
      * library name to the collection in order to ensure there are
      * no conflicts.
      */
     $libConfig = Libraries::get('li3b_users');
     $connection = isset($libConfig['useConnection']) ? $libConfig['useConnection'] : 'li3b_users';
     static::meta('connection', $connection);
 }
예제 #14
0
 /**
  * Allows a user to update their own profile.
  *
  */
 public function update()
 {
     if (!$this->request->user) {
         FlashMessage::write('You must be logged in to do that.', 'default');
         return $this->redirect('/');
     }
     // Special rules for user creation (includes unique e-mail)
     $rules = array('email' => array(array('notEmpty', 'message' => 'E-mail cannot be empty.'), array('email', 'message' => 'E-mail is not valid.'), array('uniqueEmail', 'message' => 'Sorry, this e-mail address is already registered.')));
     // Get the document from the db to edit
     $conditions = array('_id' => $this->request->user['_id']);
     $document = User::find('first', array('conditions' => $conditions));
     $existingProfilePic = !empty($document->profilePicture) ? $document->profilePicture : false;
     // Redirect if invalid user...This should not be possible.
     if (empty($document)) {
         FlashMessage::write('You must be logged in to do that.', 'default');
         return $this->redirect('/');
     }
     // If data was passed, set some more data and save
     if ($this->request->data) {
         // CSRF
         if (!RequestToken::check($this->request)) {
             RequestToken::get(array('regenerate' => true));
         } else {
             $now = new MongoDate();
             $this->request->data['modified'] = $now;
             // Add validation rules for the password IF the password and password_confirm field were passed
             if (isset($this->request->data['password']) && isset($this->request->data['passwordConfirm']) && (!empty($this->request->data['password']) && !empty($this->request->data['passwordConfirm']))) {
                 $rules['password'] = array(array('notEmpty', 'message' => 'Password cannot be empty.'), array('notEmptyHash', 'message' => 'Password cannot be empty.'), array('moreThanFive', 'message' => 'Password must be at least 6 characters long.'));
                 // ...and of course hash the password
                 $this->request->data['password'] = Password::hash($this->request->data['password']);
             } else {
                 // Otherwise, set the password to the current password.
                 $this->request->data['password'] = $document->password;
             }
             // Ensure the unique e-mail validation rule doesn't get in the way when editing users
             // So if the user being edited has the same e-mail address as the POST data...
             // Change the e-mail validation rules
             if (isset($this->request->data['email']) && $this->request->data['email'] == $document->email) {
                 $rules['email'] = array(array('notEmpty', 'message' => 'E-mail cannot be empty.'), array('email', 'message' => 'E-mail is not valid.'));
             }
             // Set the pretty URL that gets used by a lot of front-end actions.
             // Pass the document _id so that it doesn't change the pretty URL on an update.
             $this->request->data['url'] = $this->_generateUrl($document->_id);
             // Do not let roles or user active status to be adjusted via this method.
             if (isset($this->request->data['role'])) {
                 unset($this->request->data['role']);
             }
             if (isset($this->request->data['active'])) {
                 unset($this->request->data['active']);
             }
             // Profile Picture
             if (isset($this->request->data['profilePicture']['error']) && $this->request->data['profilePicture']['error'] == UPLOAD_ERR_OK) {
                 $rules['profilePicture'] = array(array('notTooLarge', 'message' => 'Profile picture cannot be larger than 250px in either dimension.'), array('invalidFileType', 'message' => 'Profile picture must be a jpg, png, or gif image.'));
                 list($width, $height) = getimagesize($this->request->data['profilePicture']['tmp_name']);
                 // Check file dimensions first.
                 // TODO: Maybe make this configurable.
                 if ($width > 250 || $height > 250) {
                     $this->request->data['profilePicture'] = 'TOO_LARGE.jpg';
                 } else {
                     // Save file to gridFS
                     $ext = substr(strrchr($this->request->data['profilePicture']['name'], '.'), 1);
                     switch (strtolower($ext)) {
                         case 'jpg':
                         case 'jpeg':
                         case 'png':
                         case 'gif':
                         case 'png':
                             $gridFile = Asset::create(array('file' => $this->request->data['profilePicture']['tmp_name'], 'filename' => (string) uniqid(php_uname('n') . '.') . '.' . $ext, 'fileExt' => $ext));
                             $gridFile->save();
                             break;
                         default:
                             $this->request->data['profilePicture'] = 'INVALID_FILE_TYPE.jpg';
                             //exit();
                             break;
                     }
                     // If file saved, set the field to associate it (and remove the old one - gotta keep it clean).
                     if (isset($gridFile) && $gridFile->_id) {
                         if ($existingProfilePic && substr($existingProfilePic, 0, 4) != 'http') {
                             $existingProfilePicId = substr($existingProfilePic, 0, -strlen(strrchr($existingProfilePic, '.')));
                             // Once last check...This REALLY can't be empty, otherwise it would remove ALL assets!
                             if (!empty($existingProfilePicId)) {
                                 Asset::remove(array('_id' => $existingProfilePicId));
                             }
                         }
                         // TODO: Maybe allow saving to disk or S3 or CloudFiles or something. Maybe.
                         $this->request->data['profilePicture'] = (string) $gridFile->_id . '.' . $ext;
                     } else {
                         if ($this->request->data['profilePicture'] != 'INVALID_FILE_TYPE.jpg') {
                             $this->request->data['profilePicture'] = null;
                         }
                     }
                 }
             } else {
                 $this->request->data['profilePicture'] = null;
             }
             // Save
             if ($document->save($this->request->data, array('validate' => $rules))) {
                 FlashMessage::write('You have successfully updated your user settings.', 'default');
                 $this->redirect(array('library' => 'li3b_users', 'controller' => 'users', 'action' => 'update'));
             } else {
                 $this->request->data['password'] = '';
                 FlashMessage::write('There was an error trying to update your user settings, please try again.', 'default');
             }
         }
     }
     $this->set(compact('document'));
 }
예제 #15
0
 * 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')));
예제 #16
0
 * 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)) {