PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Auth/BaseAuthenticate.php

https://gitlab.com/0072016/0072016-fbphp
PHP | 251 lines | 96 code | 28 blank | 127 comment | 8 complexity | 7eb51faef63b2b657f6f5f1422139abb MD5 | raw file
  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\Controller\ComponentRegistry;
  16. use Cake\Core\InstanceConfigTrait;
  17. use Cake\Event\EventListenerInterface;
  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 implements EventListenerInterface
  26. {
  27. use InstanceConfigTrait;
  28. /**
  29. * Default config for this object.
  30. *
  31. * - `fields` The fields to use to identify a user by.
  32. * - `userModel` The alias for users table, defaults to Users.
  33. * - `finder` The finder method to use to fetch user record. Defaults to 'all'.
  34. * You can set finder name as string or an array where key is finder name and value
  35. * is an array passed to `Table::find()` options.
  36. * E.g. ['finderName' => ['some_finder_option' => 'some_value']]
  37. * - `passwordHasher` Password hasher class. Can be a string specifying class name
  38. * or an array containing `className` key, any other keys will be passed as
  39. * config to the class. Defaults to 'Default'.
  40. * - Options `scope` and `contain` have been deprecated since 3.1. Use custom
  41. * finder instead to modify the query to fetch user record.
  42. *
  43. * @var array
  44. */
  45. protected $_defaultConfig = [
  46. 'fields' => [
  47. 'username' => 'username',
  48. 'password' => 'password'
  49. ],
  50. 'userModel' => 'Users',
  51. 'scope' => [],
  52. 'finder' => 'all',
  53. 'contain' => null,
  54. 'passwordHasher' => 'Default'
  55. ];
  56. /**
  57. * A Component registry, used to get more components.
  58. *
  59. * @var \Cake\Controller\ComponentRegistry
  60. */
  61. protected $_registry;
  62. /**
  63. * Password hasher instance.
  64. *
  65. * @var \Cake\Auth\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 \Cake\Controller\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, array $config = [])
  82. {
  83. $this->_registry = $registry;
  84. $this->config($config);
  85. }
  86. /**
  87. * Find a user record using the username and password provided.
  88. *
  89. * Input passwords will be hashed even when a user doesn't exist. This
  90. * helps mitigate timing attacks that are attempting to find valid usernames.
  91. *
  92. * @param string $username The username/identifier.
  93. * @param string|null $password The password, if not provided password checking is skipped
  94. * and result of find is returned.
  95. * @return bool|array Either false on failure, or an array of user data.
  96. */
  97. protected function _findUser($username, $password = null)
  98. {
  99. $result = $this->_query($username)->first();
  100. if (empty($result)) {
  101. return false;
  102. }
  103. if ($password !== null) {
  104. $hasher = $this->passwordHasher();
  105. $hashedPassword = $result->get($this->_config['fields']['password']);
  106. if (!$hasher->check($password, $hashedPassword)) {
  107. return false;
  108. }
  109. $this->_needsPasswordRehash = $hasher->needsRehash($hashedPassword);
  110. $result->unsetProperty($this->_config['fields']['password']);
  111. }
  112. return $result->toArray();
  113. }
  114. /**
  115. * Get query object for fetching user from database.
  116. *
  117. * @param string $username The username/identifier.
  118. * @return \Cake\ORM\Query
  119. */
  120. protected function _query($username)
  121. {
  122. $config = $this->_config;
  123. $table = TableRegistry::get($config['userModel']);
  124. $options = [
  125. 'conditions' => [$table->aliasField($config['fields']['username']) => $username]
  126. ];
  127. if (!empty($config['scope'])) {
  128. $options['conditions'] = array_merge($options['conditions'], $config['scope']);
  129. }
  130. if (!empty($config['contain'])) {
  131. $options['contain'] = $config['contain'];
  132. }
  133. $finder = $config['finder'];
  134. if (is_array($finder)) {
  135. $options += current($finder);
  136. $finder = key($finder);
  137. }
  138. if (!isset($options['username'])) {
  139. $options['username'] = $username;
  140. }
  141. $query = $table->find($finder, $options);
  142. return $query;
  143. }
  144. /**
  145. * Return password hasher object
  146. *
  147. * @return \Cake\Auth\AbstractPasswordHasher Password hasher instance
  148. * @throws \RuntimeException If password hasher class not found or
  149. * it does not extend AbstractPasswordHasher
  150. */
  151. public function passwordHasher()
  152. {
  153. if ($this->_passwordHasher) {
  154. return $this->_passwordHasher;
  155. }
  156. $passwordHasher = $this->_config['passwordHasher'];
  157. return $this->_passwordHasher = PasswordHasherFactory::build($passwordHasher);
  158. }
  159. /**
  160. * Returns whether or not the password stored in the repository for the logged in user
  161. * requires to be rehashed with another algorithm
  162. *
  163. * @return bool
  164. */
  165. public function needsPasswordRehash()
  166. {
  167. return $this->_needsPasswordRehash;
  168. }
  169. /**
  170. * Authenticate a user based on the request information.
  171. *
  172. * @param \Cake\Network\Request $request Request to get authentication information from.
  173. * @param \Cake\Network\Response $response A response object that can have headers added.
  174. * @return mixed Either false on failure, or an array of user data on success.
  175. */
  176. abstract public function authenticate(Request $request, Response $response);
  177. /**
  178. * Get a user based on information in the request. Primarily used by stateless authentication
  179. * systems like basic and digest auth.
  180. *
  181. * @param \Cake\Network\Request $request Request object.
  182. * @return mixed Either false or an array of user information
  183. */
  184. public function getUser(Request $request)
  185. {
  186. return false;
  187. }
  188. /**
  189. * Handle unauthenticated access attempt. In implementation valid return values
  190. * can be:
  191. *
  192. * - Null - No action taken, AuthComponent should return appropriate response.
  193. * - Cake\Network\Response - A response object, which will cause AuthComponent to
  194. * simply return that response.
  195. *
  196. * @param \Cake\Network\Request $request A request object.
  197. * @param \Cake\Network\Response $response A response object.
  198. * @return void
  199. */
  200. public function unauthenticated(Request $request, Response $response)
  201. {
  202. }
  203. /**
  204. * Returns a list of all events that this authenticate class will listen to.
  205. *
  206. * An authenticate class can listen to following events fired by AuthComponent:
  207. *
  208. * - `Auth.afterIdentify` - Fired after a user has been identified using one of
  209. * configured authenticate class. The callback function should have signature
  210. * like `afterIdentify(Event $event, array $user)` when `$user` is the
  211. * identified user record.
  212. *
  213. * - `Auth.logout` - Fired when AuthComponent::logout() is called. The callback
  214. * function should have signature like `logout(Event $event, array $user)`
  215. * where `$user` is the user about to be logged out.
  216. *
  217. * @return array List of events this class listens to. Defaults to `[]`.
  218. */
  219. public function implementedEvents()
  220. {
  221. return [];
  222. }
  223. }