1: <?php
2: /**
3: * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
4: * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
5: *
6: * Licensed under The MIT License
7: * For full copyright and license information, please see the LICENSE.txt
8: * Redistributions of files must retain the above copyright notice.
9: *
10: * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
11: * @link https://cakephp.org CakePHP(tm) Project
12: * @since 3.0.0
13: * @license https://opensource.org/licenses/mit-license.php MIT License
14: */
15: namespace Cake\Auth;
16:
17: /**
18: * A password hasher that can use multiple different hashes where only
19: * one is the preferred one. This is useful when trying to migrate an
20: * existing database of users from one password type to another.
21: */
22: class FallbackPasswordHasher extends AbstractPasswordHasher
23: {
24: /**
25: * Default config for this object.
26: *
27: * @var array
28: */
29: protected $_defaultConfig = [
30: 'hashers' => []
31: ];
32:
33: /**
34: * Holds the list of password hasher objects that will be used
35: *
36: * @var \Cake\Auth\AbstractPasswordHasher[]
37: */
38: protected $_hashers = [];
39:
40: /**
41: * Constructor
42: *
43: * @param array $config configuration options for this object. Requires the
44: * `hashers` key to be present in the array with a list of other hashers to be
45: * used
46: */
47: public function __construct(array $config = [])
48: {
49: parent::__construct($config);
50: foreach ($this->_config['hashers'] as $key => $hasher) {
51: if (is_array($hasher) && !isset($hasher['className'])) {
52: $hasher['className'] = $key;
53: }
54: $this->_hashers[] = PasswordHasherFactory::build($hasher);
55: }
56: }
57:
58: /**
59: * Generates password hash.
60: *
61: * Uses the first password hasher in the list to generate the hash
62: *
63: * @param string $password Plain text password to hash.
64: * @return string|false Password hash
65: */
66: public function hash($password)
67: {
68: return $this->_hashers[0]->hash($password);
69: }
70:
71: /**
72: * Verifies that the provided password corresponds to its hashed version
73: *
74: * This will iterate over all configured hashers until one of them returns
75: * true.
76: *
77: * @param string $password Plain text password to hash.
78: * @param string $hashedPassword Existing hashed password.
79: * @return bool True if hashes match else false.
80: */
81: public function check($password, $hashedPassword)
82: {
83: foreach ($this->_hashers as $hasher) {
84: if ($hasher->check($password, $hashedPassword)) {
85: return true;
86: }
87: }
88:
89: return false;
90: }
91:
92: /**
93: * Returns true if the password need to be rehashed, with the first hasher present
94: * in the list of hashers
95: *
96: * @param string $password The password to verify
97: * @return bool
98: */
99: public function needsRehash($password)
100: {
101: return $this->_hashers[0]->needsRehash($password);
102: }
103: }
104: