euromark 11 年之前
父节点
当前提交
36bd6f8c74
共有 2 个文件被更改,包括 143 次插入151 次删除
  1. 1 0
      Controller/Component/Auth/ModernPasswordHasher.php
  2. 142 151
      Model/Behavior/PasswordableBehavior.php

+ 1 - 0
Controller/Component/Auth/ModernPasswordHasher.php

@@ -4,6 +4,7 @@ App::uses('AbstractPasswordHasher', 'Controller/Component/Auth');
 
 /**
  * Modern password hashing class for PHP5.5+.
+ * A backport of the 3.x DefaultPasswordHasher class.
  *
  * This requires either PHP5.5+ or the password_hash() shim from
  * https://github.com/ircmaxell/password_compat

+ 142 - 151
Model/Behavior/PasswordableBehavior.php

@@ -108,6 +108,83 @@ class PasswordableBehavior extends ModelBehavior {
 	);
 
 	/**
+	 * Adding validation rules
+	 * also adds and merges config settings (direct + configure)
+	 *
+	 * @return void
+	 */
+	public function setup(Model $Model, $config = array()) {
+		$defaults = $this->_defaultConfig;
+		if ($configureDefaults = Configure::read('Passwordable')) {
+			$defaults = $configureDefaults + $defaults;
+		}
+		$this->settings[$Model->alias] = $config + $defaults;
+
+		// BC comp
+		if ($this->settings[$Model->alias]['allowEmpty']) {
+			$this->settings[$Model->alias]['require'] = false;
+		}
+
+		$formField = $this->settings[$Model->alias]['formField'];
+		$formFieldRepeat = $this->settings[$Model->alias]['formFieldRepeat'];
+		$formFieldCurrent = $this->settings[$Model->alias]['formFieldCurrent'];
+
+		if ($formField === $this->settings[$Model->alias]['field']) {
+			throw new CakeException('Invalid setup - the form field must to be different from the model field (' . $this->settings[$Model->alias]['field'] . ').');
+		}
+
+		$rules = $this->_validationRules;
+		foreach ($rules as $field => $fieldRules) {
+			foreach ($fieldRules as $key => $rule) {
+				$rule['allowEmpty'] = !$this->settings[$Model->alias]['require'];
+
+				if ($key === 'between') {
+					$rule['rule'][1] = $this->settings[$Model->alias]['minLength'];
+					$rule['message'][1] = $this->settings[$Model->alias]['minLength'];
+					$rule['rule'][2] = $this->settings[$Model->alias]['maxLength'];
+					$rule['message'][2] = $this->settings[$Model->alias]['maxLength'];
+				}
+
+				$fieldRules[$key] = $rule;
+			}
+			$rules[$field] = $fieldRules;
+		}
+
+		// Add the validation rules if not already attached
+		if (!isset($Model->validate[$formField])) {
+			$Model->validator()->add($formField, $rules['formField']);
+		}
+		if (!isset($Model->validate[$formFieldRepeat])) {
+			$ruleSet = $rules['formFieldRepeat'];
+			$ruleSet['validateIdentical']['rule'][1] = $formField;
+			$Model->validator()->add($formFieldRepeat, $ruleSet);
+		}
+
+		if ($this->settings[$Model->alias]['current'] && !isset($Model->validate[$formFieldCurrent])) {
+			$Model->validator()->add($formFieldCurrent, $rules['formFieldCurrent']);
+
+			if (!$this->settings[$Model->alias]['allowSame']) {
+				$Model->validator()->add($formField, 'validateNotSame', array(
+					'rule' => array('validateNotSame', $formField, $formFieldCurrent),
+					'message' => 'valErrPwdSameAsBefore',
+					'allowEmpty' => !$this->settings[$Model->alias]['require'],
+					'last' => true,
+				));
+			}
+		} elseif (!isset($Model->validate[$formFieldCurrent])) {
+			// Try to match the password against the hash in the DB
+			if (!$this->settings[$Model->alias]['allowSame']) {
+				$Model->validator()->add($formField, 'validateNotSame', array(
+					'rule' => array('validateNotSameHash', $formField),
+					'message' => 'valErrPwdSameAsBefore',
+					'allowEmpty' => !$this->settings[$Model->alias]['require'],
+					'last' => true,
+				));
+			}
+		}
+	}
+
+	/**
 	 * If not implemented in AppModel
 	 *
 	 * Note: requires the used Auth component to be App::uses() loaded.
@@ -143,14 +220,6 @@ class PasswordableBehavior extends ModelBehavior {
 		}
 
 		return $this->_validateSameHash($Model, $pwd);
-
-
-		if (!empty($this->settings[$Model->alias]['passwordHasher'])) {
-			$authConfig['passwordHasher'] = $this->settings[$Model->alias]['passwordHasher'];
-		}
-		$this->Auth->authenticate = array(
-			$this->settings[$Model->alias]['authType'] => $authConfig
-		);
 	}
 
 	/**
@@ -219,148 +288,6 @@ class PasswordableBehavior extends ModelBehavior {
 	}
 
 	/**
-	 * PasswordableBehavior::_validateSameHash()
-	 *
-	 * @param Model $Model
-	 * @param string $pwd
-	 * @return bool Success
-	 */
-	protected function _validateSameHash(Model $Model, $pwd) {
-		$field = $this->settings[$Model->alias]['field'];
-		$type = $this->settings[$Model->alias]['hashType'];
-		$salt = $this->settings[$Model->alias]['hashSalt'];
-		if ($this->settings[$Model->alias]['authType'] === 'Blowfish') {
-			$type = 'blowfish';
-			$salt = false;
-		}
-
-		$primaryKey = $Model->data[$Model->alias][$Model->primaryKey];
-		$dbValue = $Model->field($field, array($Model->primaryKey => $primaryKey));
-		if (!$dbValue && $pwd) {
-			return false;
-		}
-
-		if ($type === 'blowfish' && function_exists('password_hash') && !empty($this->settings[$Model->alias]['passwordHasher'])) {
-			$value = $pwd;
-		} else {
-			if ($type === 'blowfish') {
-				$salt = $dbValue;
-			}
-			$value = Security::hash($pwd, $type, $salt);
-		}
-
-		if ($type === 'blowfish' && function_exists('password_hash') && !empty($this->settings[$Model->alias]['passwordHasher'])) {
-			$PasswordHasher = $this->_getPasswordHasher($this->settings[$Model->alias]['passwordHasher']);
-			return $PasswordHasher->check($value, $dbValue);
-		}
-		return $value === $dbValue;
-	}
-
-	/**
-	 * PasswordableBehavior::_getPasswordHasher()
-	 *
-	 * @param mixed $hasher Name or options array.
-	 * @return PasswordHasher
-	 */
-	protected function _getPasswordHasher($hasher) {
-		$class = $hasher;
-		$config = array();
-		if (is_array($hasher)) {
-			$class = $hasher['className'];
-			unset($hasher['className']);
-			$config = $hasher;
-		}
-
-		list($plugin, $class) = pluginSplit($class, true);
-		$className = $class . 'PasswordHasher';
-		App::uses($className, $plugin . 'Controller/Component/Auth');
-		if (!class_exists($className)) {
-			throw new CakeException(__d('cake_dev', 'Password hasher class "%s" was not found.', $class));
-		}
-		if (!is_subclass_of($className, 'AbstractPasswordHasher')) {
-			throw new CakeException(__d('cake_dev', 'Password hasher must extend AbstractPasswordHasher class.'));
-		}
-		return new $className($config);
-	}
-
-	/**
-	 * Adding validation rules
-	 * also adds and merges config settings (direct + configure)
-	 *
-	 * @return void
-	 */
-	public function setup(Model $Model, $config = array()) {
-		$defaults = $this->_defaultConfig;
-		if ($configureDefaults = Configure::read('Passwordable')) {
-			$defaults = $configureDefaults + $defaults;
-		}
-		$this->settings[$Model->alias] = $config + $defaults;
-
-		// BC comp
-		if ($this->settings[$Model->alias]['allowEmpty']) {
-			$this->settings[$Model->alias]['require'] = false;
-		}
-
-		$formField = $this->settings[$Model->alias]['formField'];
-		$formFieldRepeat = $this->settings[$Model->alias]['formFieldRepeat'];
-		$formFieldCurrent = $this->settings[$Model->alias]['formFieldCurrent'];
-
-		if ($formField === $this->settings[$Model->alias]['field']) {
-			throw new CakeException('Invalid setup - the form field must to be different from the model field (' . $this->settings[$Model->alias]['field'] . ').');
-		}
-
-		$rules = $this->_validationRules;
-		foreach ($rules as $field => $fieldRules) {
-			foreach ($fieldRules as $key => $rule) {
-				$rule['allowEmpty'] = !$this->settings[$Model->alias]['require'];
-
-				if ($key === 'between') {
-					$rule['rule'][1] = $this->settings[$Model->alias]['minLength'];
-					$rule['message'][1] = $this->settings[$Model->alias]['minLength'];
-					$rule['rule'][2] = $this->settings[$Model->alias]['maxLength'];
-					$rule['message'][2] = $this->settings[$Model->alias]['maxLength'];
-				}
-
-				$fieldRules[$key] = $rule;
-			}
-			$rules[$field] = $fieldRules;
-		}
-
-		// Add the validation rules if not already attached
-		if (!isset($Model->validate[$formField])) {
-			$Model->validator()->add($formField, $rules['formField']);
-		}
-		if (!isset($Model->validate[$formFieldRepeat])) {
-			$ruleSet = $rules['formFieldRepeat'];
-			$ruleSet['validateIdentical']['rule'][1] = $formField;
-			$Model->validator()->add($formFieldRepeat, $ruleSet);
-		}
-
-		if ($this->settings[$Model->alias]['current'] && !isset($Model->validate[$formFieldCurrent])) {
-			$Model->validator()->add($formFieldCurrent, $rules['formFieldCurrent']);
-
-			if (!$this->settings[$Model->alias]['allowSame']) {
-				$Model->validator()->add($formField, 'validateNotSame', array(
-					'rule' => array('validateNotSame', $formField, $formFieldCurrent),
-					'message' => 'valErrPwdSameAsBefore',
-					'allowEmpty' => !$this->settings[$Model->alias]['require'],
-					'last' => true,
-				));
-			}
-		} elseif (!isset($Model->validate[$formFieldCurrent])) {
-			// Try to match the password against the hash in the DB
-			if (!$this->settings[$Model->alias]['allowSame']) {
-				$Model->validator()->add($formField, 'validateNotSame', array(
-					'rule' => array('validateNotSameHash', $formField),
-					'message' => 'valErrPwdSameAsBefore',
-					'allowEmpty' => !$this->settings[$Model->alias]['require'],
-					'last' => true,
-				));
-			}
-		}
-	}
-
-	/**
 	 * Preparing the data
 	 *
 	 * @return bool Success
@@ -456,12 +383,49 @@ class PasswordableBehavior extends ModelBehavior {
 
 		}
 
-		// Update whitelist
 		$this->_modifyWhitelist($Model, true);
 		return true;
 	}
 
 	/**
+	 * PasswordableBehavior::_validateSameHash()
+	 *
+	 * @param Model $Model
+	 * @param string $pwd
+	 * @return bool Success
+	 */
+	protected function _validateSameHash(Model $Model, $pwd) {
+		$field = $this->settings[$Model->alias]['field'];
+		$type = $this->settings[$Model->alias]['hashType'];
+		$salt = $this->settings[$Model->alias]['hashSalt'];
+		if ($this->settings[$Model->alias]['authType'] === 'Blowfish') {
+			$type = 'blowfish';
+			$salt = false;
+		}
+
+		$primaryKey = $Model->data[$Model->alias][$Model->primaryKey];
+		$dbValue = $Model->field($field, array($Model->primaryKey => $primaryKey));
+		if (!$dbValue && $pwd) {
+			return false;
+		}
+
+		if ($type === 'blowfish' && function_exists('password_hash') && !empty($this->settings[$Model->alias]['passwordHasher'])) {
+			$value = $pwd;
+		} else {
+			if ($type === 'blowfish') {
+				$salt = $dbValue;
+			}
+			$value = Security::hash($pwd, $type, $salt);
+		}
+
+		if ($type === 'blowfish' && function_exists('password_hash') && !empty($this->settings[$Model->alias]['passwordHasher'])) {
+			$PasswordHasher = $this->_getPasswordHasher($this->settings[$Model->alias]['passwordHasher']);
+			return $PasswordHasher->check($value, $dbValue);
+		}
+		return $value === $dbValue;
+	}
+
+	/**
 	 * Modify the model's whitelist.
 	 *
 	 * Since 2.5 behaviors can also modify the whitelist for validate, thus this behavior can now
@@ -491,4 +455,31 @@ class PasswordableBehavior extends ModelBehavior {
 		}
 	}
 
+	/**
+	 * PasswordableBehavior::_getPasswordHasher()
+	 *
+	 * @param mixed $hasher Name or options array.
+	 * @return PasswordHasher
+	 */
+	protected function _getPasswordHasher($hasher) {
+		$class = $hasher;
+		$config = array();
+		if (is_array($hasher)) {
+			$class = $hasher['className'];
+			unset($hasher['className']);
+			$config = $hasher;
+		}
+
+		list($plugin, $class) = pluginSplit($class, true);
+		$className = $class . 'PasswordHasher';
+		App::uses($className, $plugin . 'Controller/Component/Auth');
+		if (!class_exists($className)) {
+			throw new CakeException(__d('cake_dev', 'Password hasher class "%s" was not found.', $class));
+		}
+		if (!is_subclass_of($className, 'AbstractPasswordHasher')) {
+			throw new CakeException(__d('cake_dev', 'Password hasher must extend AbstractPasswordHasher class.'));
+		}
+		return new $className($config);
+	}
+
 }