統計
| ブランチ: | リビジョン:

pictcode / lib / Cake / Controller / Component / AuthComponent.php @ 0b1b8047

履歴 | 表示 | アノテート | ダウンロード (25.276 KB)

1 635eef61 spyder1211
<?php
2
/**
3
 * Authentication component
4
 *
5
 * Manages user logins and permissions.
6
 *
7
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
8
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
9
 *
10
 * Licensed under The MIT License
11
 * For full copyright and license information, please see the LICENSE.txt
12
 * Redistributions of files must retain the above copyright notice.
13
 *
14
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
15
 * @link          http://cakephp.org CakePHP(tm) Project
16
 * @package       Cake.Controller.Component
17
 * @since         CakePHP(tm) v 0.10.0.1076
18
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
19
 */
20
21
App::uses('Component', 'Controller');
22
App::uses('Router', 'Routing');
23
App::uses('Security', 'Utility');
24
App::uses('Debugger', 'Utility');
25
App::uses('Hash', 'Utility');
26
App::uses('CakeSession', 'Model/Datasource');
27
App::uses('BaseAuthorize', 'Controller/Component/Auth');
28
App::uses('BaseAuthenticate', 'Controller/Component/Auth');
29
App::uses('CakeEvent', 'Event');
30
31
/**
32
 * Authentication control component class
33
 *
34
 * Binds access control with user authentication and session management.
35
 *
36
 * @package       Cake.Controller.Component
37
 * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html
38
 */
39
class AuthComponent extends Component {
40
41
/**
42
 * Constant for 'all'
43
 *
44
 * @var string
45
 */
46
        const ALL = 'all';
47
48
/**
49
 * Other components utilized by AuthComponent
50
 *
51
 * @var array
52
 */
53
        public $components = array('Session', 'Flash', 'RequestHandler');
54
55
/**
56
 * An array of authentication objects to use for authenticating users. You can configure
57
 * multiple adapters and they will be checked sequentially when users are identified.
58
 *
59
 * ```
60
 *        $this->Auth->authenticate = array(
61
 *                'Form' => array(
62
 *                        'userModel' => 'Users.User'
63
 *                )
64
 *        );
65
 * ```
66
 *
67
 * Using the class name without 'Authenticate' as the key, you can pass in an array of settings for each
68
 * authentication object. Additionally you can define settings that should be set to all authentications objects
69
 * using the 'all' key:
70
 *
71
 * ```
72
 *        $this->Auth->authenticate = array(
73
 *                'all' => array(
74
 *                        'userModel' => 'Users.User',
75
 *                        'scope' => array('User.active' => 1)
76
 *                ),
77
 *                'Form',
78
 *                'Basic'
79
 *        );
80
 * ```
81
 *
82
 * You can also use AuthComponent::ALL instead of the string 'all'.
83
 *
84
 * @var array
85
 * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html
86
 */
87
        public $authenticate = array('Form');
88
89
/**
90
 * Objects that will be used for authentication checks.
91
 *
92
 * @var array
93
 */
94
        protected $_authenticateObjects = array();
95
96
/**
97
 * An array of authorization objects to use for authorizing users. You can configure
98
 * multiple adapters and they will be checked sequentially when authorization checks are done.
99
 *
100
 * ```
101
 *        $this->Auth->authorize = array(
102
 *                'Crud' => array(
103
 *                        'actionPath' => 'controllers/'
104
 *                )
105
 *        );
106
 * ```
107
 *
108
 * Using the class name without 'Authorize' as the key, you can pass in an array of settings for each
109
 * authorization object. Additionally you can define settings that should be set to all authorization objects
110
 * using the 'all' key:
111
 *
112
 * ```
113
 *        $this->Auth->authorize = array(
114
 *                'all' => array(
115
 *                        'actionPath' => 'controllers/'
116
 *                ),
117
 *                'Crud',
118
 *                'CustomAuth'
119
 *        );
120
 * ```
121
 *
122
 * You can also use AuthComponent::ALL instead of the string 'all'
123
 *
124
 * @var mixed
125
 * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#authorization
126
 */
127
        public $authorize = false;
128
129
/**
130
 * Objects that will be used for authorization checks.
131
 *
132
 * @var array
133
 */
134
        protected $_authorizeObjects = array();
135
136
/**
137
 * The name of an optional view element to render when an Ajax request is made
138
 * with an invalid or expired session
139
 *
140
 * @var string
141
 */
142
        public $ajaxLogin = null;
143
144
/**
145
 * Settings to use when Auth needs to do a flash message with SessionComponent::setFlash().
146
 * Available keys are:
147
 *
148
 * - `element` - The element to use, defaults to 'default'.
149
 * - `key` - The key to use, defaults to 'auth'
150
 * - `params` - The array of additional params to use, defaults to array()
151
 *
152
 * @var array
153
 */
154
        public $flash = array(
155
                'element' => 'default',
156
                'key' => 'auth',
157
                'params' => array()
158
        );
159
160
/**
161
 * The session key name where the record of the current user is stored. Default
162
 * key is "Auth.User". If you are using only stateless authenticators set this
163
 * to false to ensure session is not started.
164
 *
165
 * @var string
166
 */
167
        public static $sessionKey = 'Auth.User';
168
169
/**
170
 * The current user, used for stateless authentication when
171
 * sessions are not available.
172
 *
173
 * @var array
174
 */
175
        protected static $_user = array();
176
177
/**
178
 * A URL (defined as a string or array) to the controller action that handles
179
 * logins. Defaults to `/users/login`.
180
 *
181
 * @var mixed
182
 */
183
        public $loginAction = array(
184
                'controller' => 'users',
185
                'action' => 'login',
186
                'plugin' => null
187
        );
188
189
/**
190
 * Normally, if a user is redirected to the $loginAction page, the location they
191
 * were redirected from will be stored in the session so that they can be
192
 * redirected back after a successful login. If this session value is not
193
 * set, redirectUrl() method will return the URL specified in $loginRedirect.
194
 *
195
 * @var mixed
196
 * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#AuthComponent::$loginRedirect
197
 */
198
        public $loginRedirect = null;
199
200
/**
201
 * The default action to redirect to after the user is logged out. While AuthComponent does
202
 * not handle post-logout redirection, a redirect URL will be returned from AuthComponent::logout().
203
 * Defaults to AuthComponent::$loginAction.
204
 *
205
 * @var mixed
206
 * @see AuthComponent::$loginAction
207
 * @see AuthComponent::logout()
208
 */
209
        public $logoutRedirect = null;
210
211
/**
212
 * Error to display when user attempts to access an object or action to which they do not have
213
 * access.
214
 *
215
 * @var string|bool
216
 * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#AuthComponent::$authError
217
 */
218
        public $authError = null;
219
220
/**
221
 * Controls handling of unauthorized access.
222
 * - For default value `true` unauthorized user is redirected to the referrer URL
223
 *   or AuthComponent::$loginRedirect or '/'.
224
 * - If set to a string or array the value is used as a URL to redirect to.
225
 * - If set to false a ForbiddenException exception is thrown instead of redirecting.
226
 *
227
 * @var mixed
228
 */
229
        public $unauthorizedRedirect = true;
230
231
/**
232
 * Controller actions for which user validation is not required.
233
 *
234
 * @var array
235
 * @see AuthComponent::allow()
236
 */
237
        public $allowedActions = array();
238
239
/**
240
 * Request object
241
 *
242
 * @var CakeRequest
243
 */
244
        public $request;
245
246
/**
247
 * Response object
248
 *
249
 * @var CakeResponse
250
 */
251
        public $response;
252
253
/**
254
 * Method list for bound controller.
255
 *
256
 * @var array
257
 */
258
        protected $_methods = array();
259
260
/**
261
 * Initializes AuthComponent for use in the controller.
262
 *
263
 * @param Controller $controller A reference to the instantiating controller object
264
 * @return void
265
 */
266
        public function initialize(Controller $controller) {
267
                $this->request = $controller->request;
268
                $this->response = $controller->response;
269
                $this->_methods = $controller->methods;
270
271
                if (Configure::read('debug') > 0) {
272
                        Debugger::checkSecurityKeys();
273
                }
274
        }
275
276
/**
277
 * Main execution method. Handles redirecting of invalid users, and processing
278
 * of login form data.
279
 *
280
 * @param Controller $controller A reference to the instantiating controller object
281
 * @return bool
282
 */
283
        public function startup(Controller $controller) {
284
                $methods = array_flip(array_map('strtolower', $controller->methods));
285
                $action = strtolower($controller->request->params['action']);
286
287
                $isMissingAction = (
288
                        $controller->scaffold === false &&
289
                        !isset($methods[$action])
290
                );
291
292
                if ($isMissingAction) {
293
                        return true;
294
                }
295
296
                if (!$this->_setDefaults()) {
297
                        return false;
298
                }
299
300
                if ($this->_isAllowed($controller)) {
301
                        return true;
302
                }
303
304
                if (!$this->_getUser()) {
305
                        return $this->_unauthenticated($controller);
306
                }
307
308
                if ($this->_isLoginAction($controller) ||
309
                        empty($this->authorize) ||
310
                        $this->isAuthorized($this->user())
311
                ) {
312
                        return true;
313
                }
314
315
                return $this->_unauthorized($controller);
316
        }
317
318
/**
319
 * Checks whether current action is accessible without authentication.
320
 *
321
 * @param Controller $controller A reference to the instantiating controller object
322
 * @return bool True if action is accessible without authentication else false
323
 */
324
        protected function _isAllowed(Controller $controller) {
325
                $action = strtolower($controller->request->params['action']);
326
                if (in_array($action, array_map('strtolower', $this->allowedActions))) {
327
                        return true;
328
                }
329
                return false;
330
        }
331
332
/**
333
 * Handles unauthenticated access attempt. First the `unathenticated()` method
334
 * of the last authenticator in the chain will be called. The authenticator can
335
 * handle sending response or redirection as appropriate and return `true` to
336
 * indicate no furthur action is necessary. If authenticator returns null this
337
 * method redirects user to login action. If it's an ajax request and
338
 * $ajaxLogin is specified that element is rendered else a 403 http status code
339
 * is returned.
340
 *
341
 * @param Controller $controller A reference to the controller object.
342
 * @return bool True if current action is login action else false.
343
 */
344
        protected function _unauthenticated(Controller $controller) {
345
                if (empty($this->_authenticateObjects)) {
346
                        $this->constructAuthenticate();
347
                }
348
                $auth = $this->_authenticateObjects[count($this->_authenticateObjects) - 1];
349
                if ($auth->unauthenticated($this->request, $this->response)) {
350
                        return false;
351
                }
352
353
                if ($this->_isLoginAction($controller)) {
354
                        if (empty($controller->request->data)) {
355
                                if (!$this->Session->check('Auth.redirect') && env('HTTP_REFERER')) {
356
                                        $this->Session->write('Auth.redirect', $controller->referer(null, true));
357
                                }
358
                        }
359
                        return true;
360
                }
361
362
                if (!$controller->request->is('ajax')) {
363
                        $this->flash($this->authError);
364
                        $this->Session->write('Auth.redirect', $controller->request->here(false));
365
                        $controller->redirect($this->loginAction);
366
                        return false;
367
                }
368
                if (!empty($this->ajaxLogin)) {
369
                        $controller->response->statusCode(403);
370
                        $controller->viewPath = 'Elements';
371
                        $response = $controller->render($this->ajaxLogin, $this->RequestHandler->ajaxLayout);
372
                        $response->send();
373
                        $this->_stop();
374
                        return false;
375
                }
376
                $controller->response->statusCode(403);
377
                $controller->response->send();
378
                $this->_stop();
379
                return false;
380
        }
381
382
/**
383
 * Normalizes $loginAction and checks if current request URL is same as login action.
384
 *
385
 * @param Controller $controller A reference to the controller object.
386
 * @return bool True if current action is login action else false.
387
 */
388
        protected function _isLoginAction(Controller $controller) {
389
                $url = '';
390
                if (isset($controller->request->url)) {
391
                        $url = $controller->request->url;
392
                }
393
                $url = Router::normalize($url);
394
                $loginAction = Router::normalize($this->loginAction);
395
396
                return $loginAction === $url;
397
        }
398
399
/**
400
 * Handle unauthorized access attempt
401
 *
402
 * @param Controller $controller A reference to the controller object
403
 * @return bool Returns false
404
 * @throws ForbiddenException
405
 * @see AuthComponent::$unauthorizedRedirect
406
 */
407
        protected function _unauthorized(Controller $controller) {
408
                if ($this->unauthorizedRedirect === false) {
409
                        throw new ForbiddenException($this->authError);
410
                }
411
412
                $this->flash($this->authError);
413
                if ($this->unauthorizedRedirect === true) {
414
                        $default = '/';
415
                        if (!empty($this->loginRedirect)) {
416
                                $default = $this->loginRedirect;
417
                        }
418
                        $url = $controller->referer($default, true);
419
                } else {
420
                        $url = $this->unauthorizedRedirect;
421
                }
422
                $controller->redirect($url);
423
                return false;
424
        }
425
426
/**
427
 * Attempts to introspect the correct values for object properties.
428
 *
429
 * @return bool True
430
 */
431
        protected function _setDefaults() {
432
                $defaults = array(
433
                        'logoutRedirect' => $this->loginAction,
434
                        'authError' => __d('cake', 'You are not authorized to access that location.')
435
                );
436
                foreach ($defaults as $key => $value) {
437
                        if (!isset($this->{$key}) || $this->{$key} === true) {
438
                                $this->{$key} = $value;
439
                        }
440
                }
441
                return true;
442
        }
443
444
/**
445
 * Check if the provided user is authorized for the request.
446
 *
447
 * Uses the configured Authorization adapters to check whether or not a user is authorized.
448
 * Each adapter will be checked in sequence, if any of them return true, then the user will
449
 * be authorized for the request.
450
 *
451
 * @param array $user The user to check the authorization of. If empty the user in the session will be used.
452
 * @param CakeRequest $request The request to authenticate for. If empty, the current request will be used.
453
 * @return bool True if $user is authorized, otherwise false
454
 */
455
        public function isAuthorized($user = null, CakeRequest $request = null) {
456
                if (empty($user) && !$this->user()) {
457
                        return false;
458
                }
459
                if (empty($user)) {
460
                        $user = $this->user();
461
                }
462
                if (empty($request)) {
463
                        $request = $this->request;
464
                }
465
                if (empty($this->_authorizeObjects)) {
466
                        $this->constructAuthorize();
467
                }
468
                foreach ($this->_authorizeObjects as $authorizer) {
469
                        if ($authorizer->authorize($user, $request) === true) {
470
                                return true;
471
                        }
472
                }
473
                return false;
474
        }
475
476
/**
477
 * Loads the authorization objects configured.
478
 *
479
 * @return mixed Either null when authorize is empty, or the loaded authorization objects.
480
 * @throws CakeException
481
 */
482
        public function constructAuthorize() {
483
                if (empty($this->authorize)) {
484
                        return null;
485
                }
486
                $this->_authorizeObjects = array();
487
                $config = Hash::normalize((array)$this->authorize);
488
                $global = array();
489
                if (isset($config[AuthComponent::ALL])) {
490
                        $global = $config[AuthComponent::ALL];
491
                        unset($config[AuthComponent::ALL]);
492
                }
493
                foreach ($config as $class => $settings) {
494
                        list($plugin, $class) = pluginSplit($class, true);
495
                        $className = $class . 'Authorize';
496
                        App::uses($className, $plugin . 'Controller/Component/Auth');
497
                        if (!class_exists($className)) {
498
                                throw new CakeException(__d('cake_dev', 'Authorization adapter "%s" was not found.', $class));
499
                        }
500
                        if (!method_exists($className, 'authorize')) {
501
                                throw new CakeException(__d('cake_dev', 'Authorization objects must implement an %s method.', 'authorize()'));
502
                        }
503
                        $settings = array_merge($global, (array)$settings);
504
                        $this->_authorizeObjects[] = new $className($this->_Collection, $settings);
505
                }
506
                return $this->_authorizeObjects;
507
        }
508
509
/**
510
 * Takes a list of actions in the current controller for which authentication is not required, or
511
 * no parameters to allow all actions.
512
 *
513
 * You can use allow with either an array, or var args.
514
 *
515
 * `$this->Auth->allow(array('edit', 'add'));` or
516
 * `$this->Auth->allow('edit', 'add');` or
517
 * `$this->Auth->allow();` to allow all actions
518
 *
519
 * @param string|array $action Controller action name or array of actions
520
 * @return void
521
 * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#making-actions-public
522
 */
523
        public function allow($action = null) {
524
                $args = func_get_args();
525
                if (empty($args) || $action === null) {
526
                        $this->allowedActions = $this->_methods;
527
                        return;
528
                }
529
                if (isset($args[0]) && is_array($args[0])) {
530
                        $args = $args[0];
531
                }
532
                $this->allowedActions = array_merge($this->allowedActions, $args);
533
        }
534
535
/**
536
 * Removes items from the list of allowed/no authentication required actions.
537
 *
538
 * You can use deny with either an array, or var args.
539
 *
540
 * `$this->Auth->deny(array('edit', 'add'));` or
541
 * `$this->Auth->deny('edit', 'add');` or
542
 * `$this->Auth->deny();` to remove all items from the allowed list
543
 *
544
 * @param string|array $action Controller action name or array of actions
545
 * @return void
546
 * @see AuthComponent::allow()
547
 * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#making-actions-require-authorization
548
 */
549
        public function deny($action = null) {
550
                $args = func_get_args();
551
                if (empty($args) || $action === null) {
552
                        $this->allowedActions = array();
553
                        return;
554
                }
555
                if (isset($args[0]) && is_array($args[0])) {
556
                        $args = $args[0];
557
                }
558
                foreach ($args as $arg) {
559
                        $i = array_search($arg, $this->allowedActions);
560
                        if (is_int($i)) {
561
                                unset($this->allowedActions[$i]);
562
                        }
563
                }
564
                $this->allowedActions = array_values($this->allowedActions);
565
        }
566
567
/**
568
 * Maps action names to CRUD operations.
569
 *
570
 * Used for controller-based authentication. Make sure
571
 * to configure the authorize property before calling this method. As it delegates $map to all the
572
 * attached authorize objects.
573
 *
574
 * @param array $map Actions to map
575
 * @return void
576
 * @see BaseAuthorize::mapActions()
577
 * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#mapping-actions-when-using-crudauthorize
578
 * @deprecated 3.0.0 Map actions using `actionMap` config key on authorize objects instead
579
 */
580
        public function mapActions($map = array()) {
581
                if (empty($this->_authorizeObjects)) {
582
                        $this->constructAuthorize();
583
                }
584
                $mappedActions = array();
585
                foreach ($this->_authorizeObjects as $auth) {
586
                        $mappedActions = Hash::merge($mappedActions, $auth->mapActions($map));
587
                }
588
                if (empty($map)) {
589
                        return $mappedActions;
590
                }
591
        }
592
593
/**
594
 * Log a user in.
595
 *
596
 * If a $user is provided that data will be stored as the logged in user. If `$user` is empty or not
597
 * specified, the request will be used to identify a user. If the identification was successful,
598
 * the user record is written to the session key specified in AuthComponent::$sessionKey. Logging in
599
 * will also change the session id in order to help mitigate session replays.
600
 *
601
 * @param array $user Either an array of user data, or null to identify a user using the current request.
602
 * @return bool True on login success, false on failure
603
 * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#identifying-users-and-logging-them-in
604
 */
605
        public function login($user = null) {
606
                $this->_setDefaults();
607
608
                if (empty($user)) {
609
                        $user = $this->identify($this->request, $this->response);
610
                }
611
                if ($user) {
612
                        $this->Session->renew();
613
                        $this->Session->write(static::$sessionKey, $user);
614
                        $event = new CakeEvent('Auth.afterIdentify', $this, array('user' => $user));
615
                        $this->_Collection->getController()->getEventManager()->dispatch($event);
616
                }
617
                return (bool)$this->user();
618
        }
619
620
/**
621
 * Log a user out.
622
 *
623
 * Returns the logout action to redirect to. Triggers the logout() method of
624
 * all the authenticate objects, so they can perform custom logout logic.
625
 * AuthComponent will remove the session data, so there is no need to do that
626
 * in an authentication object. Logging out will also renew the session id.
627
 * This helps mitigate issues with session replays.
628
 *
629
 * @return string AuthComponent::$logoutRedirect
630
 * @see AuthComponent::$logoutRedirect
631
 * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#logging-users-out
632
 */
633
        public function logout() {
634
                $this->_setDefaults();
635
                if (empty($this->_authenticateObjects)) {
636
                        $this->constructAuthenticate();
637
                }
638
                $user = $this->user();
639
                foreach ($this->_authenticateObjects as $auth) {
640
                        $auth->logout($user);
641
                }
642
                $this->Session->delete(static::$sessionKey);
643
                $this->Session->delete('Auth.redirect');
644
                $this->Session->renew();
645
                return Router::normalize($this->logoutRedirect);
646
        }
647
648
/**
649
 * Get the current user.
650
 *
651
 * Will prefer the static user cache over sessions. The static user
652
 * cache is primarily used for stateless authentication. For stateful authentication,
653
 * cookies + sessions will be used.
654
 *
655
 * @param string $key field to retrieve. Leave null to get entire User record
656
 * @return array|null User record. or null if no user is logged in.
657
 * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#accessing-the-logged-in-user
658
 */
659
        public static function user($key = null) {
660
                if (!empty(static::$_user)) {
661
                        $user = static::$_user;
662
                } elseif (static::$sessionKey && CakeSession::check(static::$sessionKey)) {
663
                        $user = CakeSession::read(static::$sessionKey);
664
                } else {
665
                        return null;
666
                }
667
                if ($key === null) {
668
                        return $user;
669
                }
670
                return Hash::get($user, $key);
671
        }
672
673
/**
674
 * Similar to AuthComponent::user() except if the session user cannot be found, connected authentication
675
 * objects will have their getUser() methods called. This lets stateless authentication methods function correctly.
676
 *
677
 * @return bool true if a user can be found, false if one cannot.
678
 */
679
        protected function _getUser() {
680
                $user = $this->user();
681
                if ($user) {
682
                        $this->Session->delete('Auth.redirect');
683
                        return true;
684
                }
685
686
                if (empty($this->_authenticateObjects)) {
687
                        $this->constructAuthenticate();
688
                }
689
                foreach ($this->_authenticateObjects as $auth) {
690
                        $result = $auth->getUser($this->request);
691
                        if (!empty($result) && is_array($result)) {
692
                                static::$_user = $result;
693
                                return true;
694
                        }
695
                }
696
697
                return false;
698
        }
699
700
/**
701
 * Backwards compatible alias for AuthComponent::redirectUrl().
702
 *
703
 * @param string|array $url Optional URL to write as the login redirect URL.
704
 * @return string Redirect URL
705
 * @deprecated 3.0.0 Since 2.3.0, use AuthComponent::redirectUrl() instead
706
 */
707
        public function redirect($url = null) {
708
                return $this->redirectUrl($url);
709
        }
710
711
/**
712
 * Get the URL a user should be redirected to upon login.
713
 *
714
 * Pass a URL in to set the destination a user should be redirected to upon
715
 * logging in.
716
 *
717
 * If no parameter is passed, gets the authentication redirect URL. The URL
718
 * returned is as per following rules:
719
 *
720
 *  - Returns the normalized URL from session Auth.redirect value if it is
721
 *    present and for the same domain the current app is running on.
722
 *  - If there is no session value and there is a $loginRedirect, the $loginRedirect
723
 *    value is returned.
724
 *  - If there is no session and no $loginRedirect, / is returned.
725
 *
726
 * @param string|array $url Optional URL to write as the login redirect URL.
727
 * @return string Redirect URL
728
 */
729
        public function redirectUrl($url = null) {
730
                if ($url !== null) {
731
                        $redir = $url;
732
                        $this->Session->write('Auth.redirect', $redir);
733
                } elseif ($this->Session->check('Auth.redirect')) {
734
                        $redir = $this->Session->read('Auth.redirect');
735
                        $this->Session->delete('Auth.redirect');
736
737
                        if (Router::normalize($redir) === Router::normalize($this->loginAction)) {
738
                                $redir = $this->loginRedirect;
739
                        }
740
                } elseif ($this->loginRedirect) {
741
                        $redir = $this->loginRedirect;
742
                } else {
743
                        $redir = '/';
744
                }
745
                if (is_array($redir)) {
746
                        return Router::url($redir + array('base' => false));
747
                }
748
                return $redir;
749
        }
750
751
/**
752
 * Use the configured authentication adapters, and attempt to identify the user
753
 * by credentials contained in $request.
754
 *
755
 * @param CakeRequest $request The request that contains authentication data.
756
 * @param CakeResponse $response The response
757
 * @return array User record data, or false, if the user could not be identified.
758
 */
759
        public function identify(CakeRequest $request, CakeResponse $response) {
760
                if (empty($this->_authenticateObjects)) {
761
                        $this->constructAuthenticate();
762
                }
763
                foreach ($this->_authenticateObjects as $auth) {
764
                        $result = $auth->authenticate($request, $response);
765
                        if (!empty($result) && is_array($result)) {
766
                                return $result;
767
                        }
768
                }
769
                return false;
770
        }
771
772
/**
773
 * Loads the configured authentication objects.
774
 *
775
 * @return mixed Either null on empty authenticate value, or an array of loaded objects.
776
 * @throws CakeException
777
 */
778
        public function constructAuthenticate() {
779
                if (empty($this->authenticate)) {
780
                        return null;
781
                }
782
                $this->_authenticateObjects = array();
783
                $config = Hash::normalize((array)$this->authenticate);
784
                $global = array();
785
                if (isset($config[AuthComponent::ALL])) {
786
                        $global = $config[AuthComponent::ALL];
787
                        unset($config[AuthComponent::ALL]);
788
                }
789
                foreach ($config as $class => $settings) {
790
                        if (!empty($settings['className'])) {
791
                                $class = $settings['className'];
792
                                unset($settings['className']);
793
                        }
794
                        list($plugin, $class) = pluginSplit($class, true);
795
                        $className = $class . 'Authenticate';
796
                        App::uses($className, $plugin . 'Controller/Component/Auth');
797
                        if (!class_exists($className)) {
798
                                throw new CakeException(__d('cake_dev', 'Authentication adapter "%s" was not found.', $class));
799
                        }
800
                        if (!method_exists($className, 'authenticate')) {
801
                                throw new CakeException(__d('cake_dev', 'Authentication objects must implement an %s method.', 'authenticate()'));
802
                        }
803
                        $settings = array_merge($global, (array)$settings);
804
                        $auth = new $className($this->_Collection, $settings);
805
                        $this->_Collection->getController()->getEventManager()->attach($auth);
806
                        $this->_authenticateObjects[] = $auth;
807
                }
808
                return $this->_authenticateObjects;
809
        }
810
811
/**
812
 * Hash a password with the application's salt value (as defined with Configure::write('Security.salt');
813
 *
814
 * This method is intended as a convenience wrapper for Security::hash(). If you want to use
815
 * a hashing/encryption system not supported by that method, do not use this method.
816
 *
817
 * @param string $password Password to hash
818
 * @return string Hashed password
819
 * @deprecated 3.0.0 Since 2.4. Use Security::hash() directly or a password hasher object.
820
 */
821
        public static function password($password) {
822
                return Security::hash($password, null, true);
823
        }
824
825
/**
826
 * Check whether or not the current user has data in the session, and is considered logged in.
827
 *
828
 * @return bool true if the user is logged in, false otherwise
829
 * @deprecated 3.0.0 Since 2.5. Use AuthComponent::user() directly.
830
 */
831
        public function loggedIn() {
832
                return (bool)$this->user();
833
        }
834
835
/**
836
 * Set a flash message. Uses the Session component, and values from AuthComponent::$flash.
837
 *
838
 * @param string $message The message to set.
839
 * @return void
840
 */
841
        public function flash($message) {
842
                if ($message === false) {
843
                        return;
844
                }
845
                $this->Flash->set($message, $this->flash);
846
        }
847
848
}