BaseAuthenticate.php 6.1 KB

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