PageRenderTime 53ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/cake/libs/controller/components/auth.php

https://github.com/Forbin/cakephp2x
PHP | 932 lines | 494 code | 77 blank | 361 comment | 117 complexity | ab720ad5dbbec49aa0ab01877de6fb1f MD5 | raw file
  1. <?php
  2. /**
  3. * Authentication component
  4. *
  5. * Manages user logins and permissions.
  6. *
  7. * PHP Version 5.x
  8. *
  9. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  10. * Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. *
  12. * Licensed under The MIT License
  13. * Redistributions of files must retain the above copyright notice.
  14. *
  15. * @copyright Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
  16. * @link http://cakephp.org CakePHP(tm) Project
  17. * @package cake
  18. * @subpackage cake.cake.libs.controller.components
  19. * @since CakePHP(tm) v 0.10.0.1076
  20. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  21. */
  22. App::import('Core', array('Router', 'Security'), false);
  23. /**
  24. * Authentication control component class
  25. *
  26. * Binds access control with user authentication and session management.
  27. *
  28. * @package cake
  29. * @subpackage cake.cake.libs.controller.components
  30. */
  31. class AuthComponent extends Object {
  32. /**
  33. * Maintains current user login state.
  34. *
  35. * @var boolean
  36. * @access private
  37. */
  38. protected $_loggedIn = false;
  39. /**
  40. * Other components utilized by AuthComponent
  41. *
  42. * @var array
  43. * @access public
  44. */
  45. public $components = array('Session', 'RequestHandler');
  46. /**
  47. * A reference to the object used for authentication
  48. *
  49. * @var object
  50. * @access public
  51. */
  52. public $authenticate = null;
  53. /**
  54. * The name of the component to use for Authorization or set this to
  55. * 'controller' will validate against Controller::isAuthorized()
  56. * 'actions' will validate Controller::action against an AclComponent::check()
  57. * 'crud' will validate mapActions against an AclComponent::check()
  58. * array('model'=> 'name'); will validate mapActions against model $name::isAuthorized(user, controller, mapAction)
  59. * 'object' will validate Controller::action against object::isAuthorized(user, controller, action)
  60. *
  61. * @var mixed
  62. * @access public
  63. */
  64. public $authorize = false;
  65. /**
  66. * The name of an optional view element to render when an Ajax request is made
  67. * with an invalid or expired session
  68. *
  69. * @var string
  70. * @access public
  71. */
  72. public $ajaxLogin = null;
  73. /**
  74. * The name of the element used for SessionComponent::setFlash
  75. *
  76. * @var string
  77. * @access public
  78. */
  79. public $flashElement = 'default';
  80. /**
  81. * The name of the model that represents users which will be authenticated. Defaults to 'User'.
  82. *
  83. * @var string
  84. * @access public
  85. */
  86. public $userModel = 'User';
  87. /**
  88. * Additional query conditions to use when looking up and authenticating users,
  89. * i.e. array('User.is_active' => 1).
  90. *
  91. * @var array
  92. * @access public
  93. */
  94. public $userScope = array();
  95. /**
  96. * Allows you to specify non-default login name and password fields used in
  97. * $userModel, i.e. array('username' => 'login_name', 'password' => 'passwd').
  98. *
  99. * @var array
  100. * @access public
  101. */
  102. public $fields = array('username' => 'username', 'password' => 'password');
  103. /**
  104. * The session key name where the record of the current user is stored. If
  105. * unspecified, it will be "Auth.{$userModel name}".
  106. *
  107. * @var string
  108. * @access public
  109. */
  110. public $sessionKey = null;
  111. /**
  112. * If using action-based access control, this defines how the paths to action
  113. * ACO nodes is computed. If, for example, all controller nodes are nested
  114. * under an ACO node named 'Controllers', $actionPath should be set to
  115. * "Controllers/".
  116. *
  117. * @var string
  118. * @access public
  119. */
  120. public $actionPath = null;
  121. /**
  122. * A URL (defined as a string or array) to the controller action that handles
  123. * logins.
  124. *
  125. * @var mixed
  126. * @access public
  127. */
  128. public $loginAction = null;
  129. /**
  130. * Normally, if a user is redirected to the $loginAction page, the location they
  131. * were redirected from will be stored in the session so that they can be
  132. * redirected back after a successful login. If this session value is not
  133. * set, the user will be redirected to the page specified in $loginRedirect.
  134. *
  135. * @var mixed
  136. * @access public
  137. */
  138. public $loginRedirect = null;
  139. /**
  140. * The the default action to redirect to after the user is logged out. While AuthComponent does
  141. * not handle post-logout redirection, a redirect URL will be returned from AuthComponent::logout().
  142. * Defaults to AuthComponent::$loginAction.
  143. *
  144. * @var mixed
  145. * @access public
  146. * @see AuthComponent::$loginAction
  147. * @see AuthComponent::logout()
  148. */
  149. public $logoutRedirect = null;
  150. /**
  151. * The name of model or model object, or any other object has an isAuthorized method.
  152. *
  153. * @var string
  154. * @access public
  155. */
  156. public $object = null;
  157. /**
  158. * Error to display when user login fails. For security purposes, only one error is used for all
  159. * login failures, so as not to expose information on why the login failed.
  160. *
  161. * @var string
  162. * @access public
  163. */
  164. public $loginError = null;
  165. /**
  166. * Error to display when user attempts to access an object or action to which they do not have
  167. * acccess.
  168. *
  169. * @var string
  170. * @access public
  171. */
  172. public $authError = null;
  173. /**
  174. * Determines whether AuthComponent will automatically redirect and exit if login is successful.
  175. *
  176. * @var boolean
  177. * @access public
  178. */
  179. public $autoRedirect = true;
  180. /**
  181. * Controller actions for which user validation is not required.
  182. *
  183. * @var array
  184. * @access public
  185. * @see AuthComponent::allow()
  186. */
  187. public $allowedActions = array();
  188. /**
  189. * Maps actions to CRUD operations. Used for controller-based validation ($validate = 'controller').
  190. *
  191. * @var array
  192. * @access public
  193. * @see AuthComponent::mapActions()
  194. */
  195. public $actionMap = array(
  196. 'index' => 'read',
  197. 'add' => 'create',
  198. 'edit' => 'update',
  199. 'view' => 'read',
  200. 'remove' => 'delete'
  201. );
  202. /**
  203. * Form data from Controller::$data
  204. *
  205. * @var array
  206. * @access public
  207. */
  208. public $data = array();
  209. /**
  210. * Parameter data from Controller::$params
  211. *
  212. * @var array
  213. * @access public
  214. */
  215. public $params = array();
  216. /**
  217. * Method list for bound controller
  218. *
  219. * @var array
  220. * @access protected
  221. */
  222. protected $_methods = array();
  223. /**
  224. * Initializes AuthComponent for use in the controller
  225. *
  226. * @param object $controller A reference to the instantiating controller object
  227. * @return void
  228. * @access public
  229. */
  230. public function initialize($controller, $settings = array()) {
  231. $this->params = $controller->params;
  232. $crud = array('create', 'read', 'update', 'delete');
  233. $this->actionMap = array_merge($this->actionMap, array_combine($crud, $crud));
  234. $this->_methods = $controller->methods;
  235. $prefixes = Router::prefixes();
  236. if (!empty($prefixes)) {
  237. foreach ($prefixes as $prefix) {
  238. $this->actionMap = array_merge($this->actionMap, array(
  239. $prefix . '_index' => 'read',
  240. $prefix . '_add' => 'create',
  241. $prefix . '_edit' => 'update',
  242. $prefix . '_view' => 'read',
  243. $prefix . '_remove' => 'delete',
  244. $prefix . '_create' => 'create',
  245. $prefix . '_read' => 'read',
  246. $prefix . '_update' => 'update',
  247. $prefix . '_delete' => 'delete'
  248. ));
  249. }
  250. }
  251. $this->_set($settings);
  252. if (Configure::read() > 0) {
  253. App::import('Debugger');
  254. Debugger::checkSessionKey();
  255. }
  256. }
  257. /**
  258. * Main execution method. Handles redirecting of invalid users, and processing
  259. * of login form data.
  260. *
  261. * @param object $controller A reference to the instantiating controller object
  262. * @return boolean
  263. * @access public
  264. */
  265. public function startup(&$controller) {
  266. $methods = array_flip($controller->methods);
  267. $action = strtolower($controller->params['action']);
  268. $allowedActions = array_map('strtolower', $this->allowedActions);
  269. $isErrorOrTests = (
  270. strtolower($controller->name) == 'cakeerror' ||
  271. (strtolower($controller->name) == 'tests' && Configure::read() > 0)
  272. );
  273. if ($isErrorOrTests) {
  274. return true;
  275. }
  276. $isMissingAction = (
  277. $controller->scaffold === false &&
  278. !isset($methods[$action])
  279. );
  280. if ($isMissingAction) {
  281. return true;
  282. }
  283. if (!$this->__setDefaults()) {
  284. return false;
  285. }
  286. $this->data = $controller->data = $this->hashPasswords($controller->data);
  287. $url = '';
  288. if (isset($controller->params['url']['url'])) {
  289. $url = $controller->params['url']['url'];
  290. }
  291. $url = Router::normalize($url);
  292. $loginAction = Router::normalize($this->loginAction);
  293. $isAllowed = (
  294. $this->allowedActions == array('*') ||
  295. in_array($action, $allowedActions)
  296. );
  297. if ($loginAction != $url && $isAllowed) {
  298. return true;
  299. }
  300. if ($loginAction == $url) {
  301. $model = $this->getModel();
  302. if (empty($controller->data) || !isset($controller->data[$model->alias])) {
  303. if (!$this->Session->check('Auth.redirect') && env('HTTP_REFERER')) {
  304. $this->Session->write('Auth.redirect', $controller->referer(null, true));
  305. }
  306. return false;
  307. }
  308. $isValid = !empty($controller->data[$model->alias][$this->fields['username']]) &&
  309. !empty($controller->data[$model->alias][$this->fields['password']]);
  310. if ($isValid) {
  311. $username = $controller->data[$model->alias][$this->fields['username']];
  312. $password = $controller->data[$model->alias][$this->fields['password']];
  313. $data = array(
  314. $model->alias . '.' . $this->fields['username'] => $username,
  315. $model->alias . '.' . $this->fields['password'] => $password
  316. );
  317. if ($this->login($data)) {
  318. if ($this->autoRedirect) {
  319. $controller->redirect($this->redirect(), null, true);
  320. }
  321. return true;
  322. }
  323. }
  324. $this->Session->setFlash($this->loginError, $this->flashElement, array(), 'auth');
  325. $controller->data[$model->alias][$this->fields['password']] = null;
  326. return false;
  327. } else {
  328. if (!$this->user()) {
  329. if (!$this->RequestHandler->isAjax()) {
  330. $this->Session->setFlash($this->authError, $this->flashElement, array(), 'auth');
  331. if (!empty($controller->params['url']) && count($controller->params['url']) >= 2) {
  332. $query = $controller->params['url'];
  333. unset($query['url'], $query['ext']);
  334. $url .= Router::queryString($query, array());
  335. }
  336. $this->Session->write('Auth.redirect', $url);
  337. $controller->redirect($loginAction);
  338. return false;
  339. } elseif (!empty($this->ajaxLogin)) {
  340. $controller->viewPath = 'elements';
  341. echo $controller->render($this->ajaxLogin, $this->RequestHandler->ajaxLayout);
  342. $this->_stop();
  343. return false;
  344. } else {
  345. $controller->redirect(null, 403);
  346. }
  347. }
  348. }
  349. if (!$this->authorize) {
  350. return true;
  351. }
  352. extract($this->__authType());
  353. switch ($type) {
  354. case 'controller':
  355. $this->object = $controller;
  356. break;
  357. case 'crud':
  358. case 'actions':
  359. if (isset($controller->Acl)) {
  360. $this->Acl = $controller->Acl;
  361. } else {
  362. $err = 'Could not find AclComponent. Please include Acl in ';
  363. $err .= 'Controller::$components.';
  364. trigger_error(__($err, true), E_USER_WARNING);
  365. }
  366. break;
  367. case 'model':
  368. if (!isset($object)) {
  369. $hasModel = (
  370. isset($controller->{$controller->modelClass}) &&
  371. is_object($controller->{$controller->modelClass})
  372. );
  373. $isUses = (
  374. !empty($controller->uses) && isset($controller->{$controller->uses[0]}) &&
  375. is_object($controller->{$controller->uses[0]})
  376. );
  377. if ($hasModel) {
  378. $object = $controller->modelClass;
  379. } elseif ($isUses) {
  380. $object = $controller->uses[0];
  381. }
  382. }
  383. $type = array('model' => $object);
  384. break;
  385. }
  386. if ($this->isAuthorized($type)) {
  387. return true;
  388. }
  389. $this->Session->setFlash($this->authError, $this->flashElement, array(), 'auth');
  390. $controller->redirect($controller->referer(), null, true);
  391. return false;
  392. }
  393. /**
  394. * Attempts to introspect the correct values for object properties including
  395. * $userModel and $sessionKey.
  396. *
  397. * @param object $controller A reference to the instantiating controller object
  398. * @return boolean
  399. * @access private
  400. */
  401. public function __setDefaults() {
  402. if (empty($this->userModel)) {
  403. trigger_error(__("Could not find \$userModel. Please set AuthComponent::\$userModel in beforeFilter().", true), E_USER_WARNING);
  404. return false;
  405. }
  406. $defaults = array(
  407. 'loginAction' => array(
  408. 'controller' => Inflector::underscore(Inflector::pluralize($this->userModel)),
  409. 'action' => 'login'
  410. ),
  411. 'sessionKey' => 'Auth.' . $this->userModel,
  412. 'logoutRedirect' => $this->loginAction,
  413. 'loginError' => __('Login failed. Invalid username or password.', true),
  414. 'authError' => __('You are not authorized to access that location.', true)
  415. );
  416. foreach ($defaults as $key => $value) {
  417. if (empty($this->{$key})) {
  418. $this->{$key} = $value;
  419. }
  420. }
  421. return true;
  422. }
  423. /**
  424. * Determines whether the given user is authorized to perform an action. The type of
  425. * authorization used is based on the value of AuthComponent::$authorize or the
  426. * passed $type param.
  427. *
  428. * Types:
  429. * 'controller' will validate against Controller::isAuthorized() if controller instance is
  430. * passed in $object
  431. * 'actions' will validate Controller::action against an AclComponent::check()
  432. * 'crud' will validate mapActions against an AclComponent::check()
  433. * array('model'=> 'name'); will validate mapActions against model
  434. * $name::isAuthorized(user, controller, mapAction)
  435. * 'object' will validate Controller::action against
  436. * object::isAuthorized(user, controller, action)
  437. *
  438. * @param string $type Type of authorization
  439. * @param mixed $object object, model object, or model name
  440. * @param mixed $user The user to check the authorization of
  441. * @return boolean True if $user is authorized, otherwise false
  442. * @access public
  443. */
  444. public function isAuthorized($type = null, $object = null, $user = null) {
  445. if (empty($user) && !$this->user()) {
  446. return false;
  447. } elseif (empty($user)) {
  448. $user = $this->user();
  449. }
  450. extract($this->__authType($type));
  451. if (!$object) {
  452. $object = $this->object;
  453. }
  454. $valid = false;
  455. switch ($type) {
  456. case 'controller':
  457. $valid = $object->isAuthorized();
  458. break;
  459. case 'actions':
  460. $valid = $this->Acl->check($user, $this->action());
  461. break;
  462. case 'crud':
  463. $this->mapActions();
  464. if (!isset($this->actionMap[$this->params['action']])) {
  465. $err = 'Auth::startup() - Attempted access of un-mapped action "%1$s" in';
  466. $err .= ' controller "%2$s"';
  467. trigger_error(
  468. sprintf(__($err, true), $this->params['action'], $this->params['controller']),
  469. E_USER_WARNING
  470. );
  471. } else {
  472. $valid = $this->Acl->check(
  473. $user,
  474. $this->action(':controller'),
  475. $this->actionMap[$this->params['action']]
  476. );
  477. }
  478. break;
  479. case 'model':
  480. $this->mapActions();
  481. $action = $this->params['action'];
  482. if (isset($this->actionMap[$action])) {
  483. $action = $this->actionMap[$action];
  484. }
  485. if (is_string($object)) {
  486. $object = $this->getModel($object);
  487. }
  488. case 'object':
  489. if (!isset($action)) {
  490. $action = $this->action(':action');
  491. }
  492. if (empty($object)) {
  493. trigger_error(sprintf(__('Could not find %s. Set AuthComponent::$object in beforeFilter() or pass a valid object', true), get_class($object)), E_USER_WARNING);
  494. return;
  495. }
  496. if (method_exists($object, 'isAuthorized')) {
  497. $valid = $object->isAuthorized($user, $this->action(':controller'), $action);
  498. } elseif ($object) {
  499. trigger_error(sprintf(__('%s::isAuthorized() is not defined.', true), get_class($object)), E_USER_WARNING);
  500. }
  501. break;
  502. case null:
  503. case false:
  504. return true;
  505. break;
  506. default:
  507. trigger_error(__('Auth::isAuthorized() - $authorize is set to an incorrect value. Allowed settings are: "actions", "crud", "model" or null.', true), E_USER_WARNING);
  508. break;
  509. }
  510. return $valid;
  511. }
  512. /**
  513. * Get authorization type
  514. *
  515. * @param string $auth Type of authorization
  516. * @return array Associative array with: type, object
  517. * @access private
  518. */
  519. public function __authType($auth = null) {
  520. if ($auth == null) {
  521. $auth = $this->authorize;
  522. }
  523. $object = null;
  524. if (is_array($auth)) {
  525. $type = key($auth);
  526. $object = $auth[$type];
  527. } else {
  528. $type = $auth;
  529. return compact('type');
  530. }
  531. return compact('type', 'object');
  532. }
  533. /**
  534. * Takes a list of actions in the current controller for which authentication is not required, or
  535. * no parameters to allow all actions.
  536. *
  537. * @param mixed $action Controller action name or array of actions
  538. * @param string $action Controller action name
  539. * @param string ... etc.
  540. * @return void
  541. * @access public
  542. */
  543. public function allow() {
  544. $args = func_get_args();
  545. if (empty($args) || $args == array('*')) {
  546. $this->allowedActions = $this->_methods;
  547. } else {
  548. if (isset($args[0]) && is_array($args[0])) {
  549. $args = $args[0];
  550. }
  551. $this->allowedActions = array_merge($this->allowedActions, array_map('strtolower', $args));
  552. }
  553. }
  554. /**
  555. * Removes items from the list of allowed actions.
  556. *
  557. * @param mixed $action Controller action name or array of actions
  558. * @param string $action Controller action name
  559. * @param string ... etc.
  560. * @return void
  561. * @see AuthComponent::allow()
  562. * @access public
  563. */
  564. public function deny() {
  565. $args = func_get_args();
  566. if (isset($args[0]) && is_array($args[0])) {
  567. $args = $args[0];
  568. }
  569. foreach ($args as $arg) {
  570. $i = array_search(strtolower($arg), $this->allowedActions);
  571. if (is_int($i)) {
  572. unset($this->allowedActions[$i]);
  573. }
  574. }
  575. $this->allowedActions = array_values($this->allowedActions);
  576. }
  577. /**
  578. * Maps action names to CRUD operations. Used for controller-based authentication.
  579. *
  580. * @param array $map Actions to map
  581. * @return void
  582. * @access public
  583. */
  584. public function mapActions($map = array()) {
  585. $crud = array('create', 'read', 'update', 'delete');
  586. foreach ($map as $action => $type) {
  587. if (in_array($action, $crud) && is_array($type)) {
  588. foreach ($type as $typedAction) {
  589. $this->actionMap[$typedAction] = $action;
  590. }
  591. } else {
  592. $this->actionMap[$action] = $type;
  593. }
  594. }
  595. }
  596. /**
  597. * Manually log-in a user with the given parameter data. The $data provided can be any data
  598. * structure used to identify a user in AuthComponent::identify(). If $data is empty or not
  599. * specified, POST data from Controller::$data will be used automatically.
  600. *
  601. * After (if) login is successful, the user record is written to the session key specified in
  602. * AuthComponent::$sessionKey.
  603. *
  604. * @param mixed $data User object
  605. * @return boolean True on login success, false on failure
  606. * @access public
  607. */
  608. public function login($data = null) {
  609. $this->__setDefaults();
  610. $this->_loggedIn = false;
  611. if (empty($data)) {
  612. $data = $this->data;
  613. }
  614. if ($user = $this->identify($data)) {
  615. $this->Session->write($this->sessionKey, $user);
  616. $this->_loggedIn = true;
  617. }
  618. return $this->_loggedIn;
  619. }
  620. /**
  621. * Logs a user out, and returns the login action to redirect to.
  622. *
  623. * @param mixed $url Optional URL to redirect the user to after logout
  624. * @return string AuthComponent::$loginAction
  625. * @see AuthComponent::$loginAction
  626. * @access public
  627. */
  628. public function logout() {
  629. $this->__setDefaults();
  630. $this->Session->delete($this->sessionKey);
  631. $this->Session->delete('Auth.redirect');
  632. $this->_loggedIn = false;
  633. return Router::normalize($this->logoutRedirect);
  634. }
  635. /**
  636. * Get the current user from the session.
  637. *
  638. * @param string $key field to retrive. Leave null to get entire User record
  639. * @return mixed User record. or null if no user is logged in.
  640. * @access public
  641. */
  642. public function user($key = null) {
  643. $this->__setDefaults();
  644. if (!$this->Session->check($this->sessionKey)) {
  645. return null;
  646. }
  647. if ($key == null) {
  648. $model = $this->getModel();
  649. return array($model->alias => $this->Session->read($this->sessionKey));
  650. } else {
  651. $user = $this->Session->read($this->sessionKey);
  652. if (isset($user[$key])) {
  653. return $user[$key];
  654. }
  655. return null;
  656. }
  657. }
  658. /**
  659. * If no parameter is passed, gets the authentication redirect URL.
  660. *
  661. * @param mixed $url Optional URL to write as the login redirect URL.
  662. * @return string Redirect URL
  663. * @access public
  664. */
  665. public function redirect($url = null) {
  666. if (!is_null($url)) {
  667. $redir = $url;
  668. $this->Session->write('Auth.redirect', $redir);
  669. } elseif ($this->Session->check('Auth.redirect')) {
  670. $redir = $this->Session->read('Auth.redirect');
  671. $this->Session->delete('Auth.redirect');
  672. if (Router::normalize($redir) == Router::normalize($this->loginAction)) {
  673. $redir = $this->loginRedirect;
  674. }
  675. } else {
  676. $redir = $this->loginRedirect;
  677. }
  678. return Router::normalize($redir);
  679. }
  680. /**
  681. * Validates a user against an abstract object.
  682. *
  683. * @param mixed $object The object to validate the user against.
  684. * @param mixed $user Optional. The identity of the user to be validated.
  685. * Uses the current user session if none specified. For
  686. * valid forms of identifying users, see
  687. * AuthComponent::identify().
  688. * @param string $action Optional. The action to validate against.
  689. * @see AuthComponent::identify()
  690. * @return boolean True if the user validates, false otherwise.
  691. * @access public
  692. */
  693. public function validate($object, $user = null, $action = null) {
  694. if (empty($user)) {
  695. $user = $this->user();
  696. }
  697. if (empty($user)) {
  698. return false;
  699. }
  700. return $this->Acl->check($user, $object, $action);
  701. }
  702. /**
  703. * Returns the path to the ACO node bound to a controller/action.
  704. *
  705. * @param string $action Optional. The controller/action path to validate the
  706. * user against. The current request action is used if
  707. * none is specified.
  708. * @return boolean ACO node path
  709. * @access public
  710. */
  711. public function action($action = ':plugin/:controller/:action') {
  712. $plugin = empty($this->params['plugin']) ? null : Inflector::camelize($this->params['plugin']) . '/';
  713. return str_replace(
  714. array(':controller', ':action', ':plugin/'),
  715. array(Inflector::camelize($this->params['controller']), $this->params['action'], $plugin),
  716. $this->actionPath . $action
  717. );
  718. }
  719. /**
  720. * Returns a reference to the model object specified, and attempts
  721. * to load it if it is not found.
  722. *
  723. * @param string $name Model name (defaults to AuthComponent::$userModel)
  724. * @return object A reference to a model object
  725. * @access public
  726. */
  727. public function &getModel($name = null) {
  728. $model = null;
  729. if (!$name) {
  730. $name = $this->userModel;
  731. }
  732. $model = ClassRegistry::init($name);
  733. if (empty($model)) {
  734. trigger_error(__('Auth::getModel() - Model is not set or could not be found', true), E_USER_WARNING);
  735. return null;
  736. }
  737. return $model;
  738. }
  739. /**
  740. * Identifies a user based on specific criteria.
  741. *
  742. * @param mixed $user Optional. The identity of the user to be validated.
  743. * Uses the current user session if none specified.
  744. * @param array $conditions Optional. Additional conditions to a find.
  745. * @return array User record data, or null, if the user could not be identified.
  746. * @access public
  747. */
  748. public function identify($user = null, $conditions = null) {
  749. if ($conditions === false) {
  750. $conditions = null;
  751. } elseif (is_array($conditions)) {
  752. $conditions = array_merge((array)$this->userScope, $conditions);
  753. } else {
  754. $conditions = $this->userScope;
  755. }
  756. $model = $this->getModel();
  757. if (empty($user)) {
  758. $user = $this->user();
  759. if (empty($user)) {
  760. return null;
  761. }
  762. } elseif (is_object($user) && is_a($user, 'Model')) {
  763. if (!$user->exists()) {
  764. return null;
  765. }
  766. $user = $user->read();
  767. $user = $user[$model->alias];
  768. } elseif (is_array($user) && isset($user[$model->alias])) {
  769. $user = $user[$model->alias];
  770. }
  771. if (is_array($user) && (isset($user[$this->fields['username']]) || isset($user[$model->alias . '.' . $this->fields['username']]))) {
  772. if (isset($user[$this->fields['username']]) && !empty($user[$this->fields['username']]) && !empty($user[$this->fields['password']])) {
  773. if (trim($user[$this->fields['username']]) == '=' || trim($user[$this->fields['password']]) == '=') {
  774. return false;
  775. }
  776. $find = array(
  777. $model->alias.'.'.$this->fields['username'] => $user[$this->fields['username']],
  778. $model->alias.'.'.$this->fields['password'] => $user[$this->fields['password']]
  779. );
  780. } elseif (isset($user[$model->alias . '.' . $this->fields['username']]) && !empty($user[$model->alias . '.' . $this->fields['username']])) {
  781. if (trim($user[$model->alias . '.' . $this->fields['username']]) == '=' || trim($user[$model->alias . '.' . $this->fields['password']]) == '=') {
  782. return false;
  783. }
  784. $find = array(
  785. $model->alias.'.'.$this->fields['username'] => $user[$model->alias . '.' . $this->fields['username']],
  786. $model->alias.'.'.$this->fields['password'] => $user[$model->alias . '.' . $this->fields['password']]
  787. );
  788. } else {
  789. return false;
  790. }
  791. $data = $model->find('first', array(
  792. 'conditions' => array_merge($find, $conditions),
  793. 'recursive' => 0
  794. ));
  795. if (empty($data) || empty($data[$model->alias])) {
  796. return null;
  797. }
  798. } elseif (!empty($user) && is_string($user)) {
  799. $data = $model->find('first', array(
  800. 'conditions' => array_merge(array($model->escapeField() => $user), $conditions),
  801. ));
  802. if (empty($data) || empty($data[$model->alias])) {
  803. return null;
  804. }
  805. }
  806. if (!empty($data)) {
  807. if (!empty($data[$model->alias][$this->fields['password']])) {
  808. unset($data[$model->alias][$this->fields['password']]);
  809. }
  810. return $data[$model->alias];
  811. }
  812. return null;
  813. }
  814. /**
  815. * Hash any passwords found in $data using $userModel and $fields['password']
  816. *
  817. * @param array $data Set of data to look for passwords
  818. * @return array Data with passwords hashed
  819. * @access public
  820. */
  821. public function hashPasswords($data) {
  822. if (is_object($this->authenticate) && method_exists($this->authenticate, 'hashPasswords')) {
  823. return $this->authenticate->hashPasswords($data);
  824. }
  825. $model = $this->getModel();
  826. if (is_array($data) && isset($data[$model->alias])) {
  827. if (isset($data[$model->alias][$this->fields['username']]) && isset($data[$model->alias][$this->fields['password']])) {
  828. $data[$model->alias][$this->fields['password']] = $this->password($data[$model->alias][$this->fields['password']]);
  829. }
  830. }
  831. return $data;
  832. }
  833. /**
  834. * Hash a password with the application's salt value (as defined with Configure::write('Security.salt');
  835. *
  836. * @param string $password Password to hash
  837. * @return string Hashed password
  838. * @access public
  839. */
  840. public function password($password) {
  841. return Security::hash($password, null, true);
  842. }
  843. /**
  844. * Component shutdown. If user is logged in, wipe out redirect.
  845. *
  846. * @param object $controller Instantiating controller
  847. * @access public
  848. */
  849. public function shutdown(&$controller) {
  850. if ($this->_loggedIn) {
  851. $this->Session->delete('Auth.redirect');
  852. }
  853. }
  854. }
  855. ?>