BaseAuthenticate.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://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. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  13. */
  14. namespace Cake\Auth;
  15. use Cake\Auth\PasswordHasherFactory;
  16. use Cake\Controller\ComponentRegistry;
  17. use Cake\Core\InstanceConfigTrait;
  18. use Cake\Network\Request;
  19. use Cake\Network\Response;
  20. use Cake\ORM\TableRegistry;
  21. /**
  22. * Base Authentication class with common methods and properties.
  23. *
  24. */
  25. abstract class BaseAuthenticate {
  26. use InstanceConfigTrait;
  27. /**
  28. * Default config for this object.
  29. *
  30. * - `fields` The fields to use to identify a user by.
  31. * - `userModel` The alias for users table, defaults to Users.
  32. * - `scope` Additional conditions to use when looking up and authenticating users,
  33. * i.e. `['Users.is_active' => 1].`
  34. * - `contain` Extra models to contain and store in session.
  35. * - `passwordHasher` Password hasher class. Can be a string specifying class name
  36. * or an array containing `className` key, any other keys will be passed as
  37. * config to the class. Defaults to 'Default'.
  38. *
  39. * @var array
  40. */
  41. protected $_defaultConfig = [
  42. 'fields' => [
  43. 'username' => 'username',
  44. 'password' => 'password'
  45. ],
  46. 'userModel' => 'Users',
  47. 'scope' => [],
  48. 'contain' => null,
  49. 'passwordHasher' => 'Default'
  50. ];
  51. /**
  52. * A Component registry, used to get more components.
  53. *
  54. * @var ComponentRegistry
  55. */
  56. protected $_registry;
  57. /**
  58. * Password hasher instance.
  59. *
  60. * @var AbstractPasswordHasher
  61. */
  62. protected $_passwordHasher;
  63. /**
  64. * Whether or not the user authenticated by this class
  65. * requires their password to be rehashed with another algorithm.
  66. *
  67. * @var bool
  68. */
  69. protected $_needsPasswordRehash = false;
  70. /**
  71. * Constructor
  72. *
  73. * @param \Cake\Controller\ComponentRegistry $registry The Component registry used on this request.
  74. * @param array $config Array of config to use.
  75. */
  76. public function __construct(ComponentRegistry $registry, array $config = []) {
  77. $this->_registry = $registry;
  78. $this->config($config);
  79. }
  80. /**
  81. * Find a user record using the username and password provided.
  82. *
  83. * Input passwords will be hashed even when a user doesn't exist. This
  84. * helps mitigate timing attacks that are attempting to find valid usernames.
  85. *
  86. * @param string $username The username/identifier.
  87. * @param string $password The password, if not provide password checking is skipped
  88. * and result of find is returned.
  89. * @return bool|array Either false on failure, or an array of user data.
  90. */
  91. protected function _findUser($username, $password = null) {
  92. $userModel = $this->_config['userModel'];
  93. list(, $model) = pluginSplit($userModel);
  94. $fields = $this->_config['fields'];
  95. $conditions = [$model . '.' . $fields['username'] => $username];
  96. $scope = $this->_config['scope'];
  97. if ($scope) {
  98. $conditions = array_merge($conditions, $scope);
  99. }
  100. $table = TableRegistry::get($userModel)->find('all');
  101. $contain = $this->_config['contain'];
  102. if ($contain) {
  103. $table = $table->contain($contain);
  104. }
  105. $result = $table
  106. ->where($conditions)
  107. ->hydrate(false)
  108. ->first();
  109. if (empty($result)) {
  110. return false;
  111. }
  112. if ($password !== null) {
  113. $hasher = $this->passwordHasher();
  114. $hashedPassword = $result[$fields['password']];
  115. if (!$hasher->check($password, $hashedPassword)) {
  116. return false;
  117. }
  118. $this->_needsPasswordRehash = $hasher->needsRehash($hashedPassword);
  119. unset($result[$fields['password']]);
  120. }
  121. return $result;
  122. }
  123. /**
  124. * Return password hasher object
  125. *
  126. * @return AbstractPasswordHasher Password hasher instance
  127. * @throws \RuntimeException If password hasher class not found or
  128. * it does not extend AbstractPasswordHasher
  129. */
  130. public function passwordHasher() {
  131. if ($this->_passwordHasher) {
  132. return $this->_passwordHasher;
  133. }
  134. $passwordHasher = $this->_config['passwordHasher'];
  135. return $this->_passwordHasher = PasswordHasherFactory::build($passwordHasher);
  136. }
  137. /**
  138. * Returns whether or not the password stored in the repository for the logged in user
  139. * requires to be rehashed with another algorithm
  140. *
  141. * @return bool
  142. */
  143. public function needsPasswordRehash() {
  144. return $this->_needsPasswordRehash;
  145. }
  146. /**
  147. * Authenticate a user based on the request information.
  148. *
  149. * @param \Cake\Network\Request $request Request to get authentication information from.
  150. * @param \Cake\Network\Response $response A response object that can have headers added.
  151. * @return mixed Either false on failure, or an array of user data on success.
  152. */
  153. abstract public function authenticate(Request $request, Response $response);
  154. /**
  155. * Allows you to hook into AuthComponent::logout(),
  156. * and implement specialized logout behavior.
  157. *
  158. * All attached authentication objects will have this method
  159. * called when a user logs out.
  160. *
  161. * @param array $user The user about to be logged out.
  162. * @return void
  163. */
  164. public function logout(array $user) {
  165. }
  166. /**
  167. * Get a user based on information in the request. Primarily used by stateless authentication
  168. * systems like basic and digest auth.
  169. *
  170. * @param \Cake\Network\Request $request Request object.
  171. * @return mixed Either false or an array of user information
  172. */
  173. public function getUser(Request $request) {
  174. return false;
  175. }
  176. /**
  177. * Handle unauthenticated access attempt. In implementation valid return values
  178. * can be:
  179. *
  180. * - Null - No action taken, AuthComponent should return appropriate response.
  181. * - Cake\Network\Response - A response object, which will cause AuthComponent to
  182. * simply return that response.
  183. *
  184. * @param \Cake\Network\Request $request A request object.
  185. * @param \Cake\Network\Response $response A response object.
  186. * @return void
  187. */
  188. public function unauthenticated(Request $request, Response $response) {
  189. }
  190. }