00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 App::import(array('Router', 'Security'));
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 class AuthComponent extends Object {
00040
00041
00042
00043
00044
00045
00046 var $_loggedIn = false;
00047
00048
00049
00050
00051
00052
00053 var $components = array('Session', 'RequestHandler');
00054
00055
00056
00057
00058
00059
00060 var $authenticate = null;
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 var $authorize = false;
00073
00074
00075
00076
00077
00078
00079
00080 var $ajaxLogin = null;
00081
00082
00083
00084
00085
00086
00087 var $userModel = 'User';
00088
00089
00090
00091
00092
00093
00094
00095 var $userScope = array();
00096
00097
00098
00099
00100
00101
00102
00103 var $fields = array('username' => 'username', 'password' => 'password');
00104
00105
00106
00107
00108
00109
00110
00111 var $sessionKey = null;
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 var $actionPath = null;
00122
00123
00124
00125
00126
00127
00128
00129 var $loginAction = null;
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 var $loginRedirect = null;
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 var $logoutRedirect = null;
00151
00152
00153
00154
00155
00156
00157 var $object = null;
00158
00159
00160
00161
00162
00163
00164
00165 var $loginError = null;
00166
00167
00168
00169
00170
00171
00172
00173 var $authError = null;
00174
00175
00176
00177
00178
00179
00180 var $autoRedirect = true;
00181
00182
00183
00184
00185
00186
00187
00188 var $allowedActions = array();
00189
00190
00191
00192
00193
00194
00195
00196 var $actionMap = array(
00197 'index' => 'read',
00198 'add' => 'create',
00199 'edit' => 'update',
00200 'view' => 'read',
00201 'remove' => 'delete'
00202 );
00203
00204
00205
00206
00207
00208
00209 var $data = array();
00210
00211
00212
00213
00214
00215
00216 var $params = array();
00217
00218
00219
00220
00221
00222
00223 var $_methods = array();
00224
00225
00226
00227
00228
00229
00230
00231 function initialize(&$controller) {
00232 $this->params = $controller->params;
00233 $crud = array('create', 'read', 'update', 'delete');
00234 $this->actionMap = array_merge($this->actionMap, array_combine($crud, $crud));
00235 $this->_methods = $controller->methods;
00236
00237 $admin = Configure::read('Routing.admin');
00238 if (!empty($admin)) {
00239 $this->actionMap = array_merge($this->actionMap, array(
00240 $admin . '_index' => 'read',
00241 $admin . '_add' => 'create',
00242 $admin . '_edit' => 'update',
00243 $admin . '_view' => 'read',
00244 $admin . '_remove' => 'delete',
00245 $admin . '_create' => 'create',
00246 $admin . '_read' => 'read',
00247 $admin . '_update' => 'update',
00248 $admin . '_delete' => 'delete'
00249 ));
00250 }
00251 if (Configure::read() > 0) {
00252 App::import('Debugger');
00253 Debugger::checkSessionKey();
00254 }
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264 function startup(&$controller) {
00265 $methods = array_flip($controller->methods);
00266 $action = strtolower($controller->params['action']);
00267 $allowedActions = array_map('strtolower', $this->allowedActions);
00268
00269 $isErrorOrTests = (
00270 strtolower($controller->name) == 'cakeerror' ||
00271 (strtolower($controller->name) == 'tests' && Configure::read() > 0)
00272 );
00273 if ($isErrorOrTests) {
00274 return true;
00275 }
00276
00277 $isMissingAction = (
00278 $controller->scaffold === false &&
00279 !isset($methods[$action])
00280 );
00281
00282 if ($isMissingAction) {
00283 return true;
00284 }
00285
00286 if (!$this->__setDefaults()) {
00287 return false;
00288 }
00289
00290 $this->data = $controller->data = $this->hashPasswords($controller->data);
00291 $url = '';
00292
00293 if (isset($controller->params['url']['url'])) {
00294 $url = $controller->params['url']['url'];
00295 }
00296 $url = Router::normalize($url);
00297 $loginAction = Router::normalize($this->loginAction);
00298
00299 $isAllowed = (
00300 $this->allowedActions == array('*') ||
00301 in_array($action, $allowedActions)
00302 );
00303
00304 if ($loginAction != $url && $isAllowed) {
00305 return true;
00306 }
00307
00308 if ($loginAction == $url) {
00309 if (empty($controller->data) || !isset($controller->data[$this->userModel])) {
00310 if (!$this->Session->check('Auth.redirect') && env('HTTP_REFERER')) {
00311 $this->Session->write('Auth.redirect', $controller->referer(null, true));
00312 }
00313 return false;
00314 }
00315
00316 $isValid = !empty($controller->data[$this->userModel][$this->fields['username']]) &&
00317 !empty($controller->data[$this->userModel][$this->fields['password']]);
00318
00319 if ($isValid) {
00320 $username = $controller->data[$this->userModel][$this->fields['username']];
00321 $password = $controller->data[$this->userModel][$this->fields['password']];
00322
00323 $data = array(
00324 $this->userModel . '.' . $this->fields['username'] => $username,
00325 $this->userModel . '.' . $this->fields['password'] => $password
00326 );
00327
00328 if ($this->login($data)) {
00329 if ($this->autoRedirect) {
00330 $controller->redirect($this->redirect(), null, true);
00331 }
00332 return true;
00333 }
00334 }
00335
00336 $this->Session->setFlash($this->loginError, 'default', array(), 'auth');
00337 $controller->data[$this->userModel][$this->fields['password']] = null;
00338 return false;
00339 } else {
00340 if (!$this->user()) {
00341 if (!$this->RequestHandler->isAjax()) {
00342 $this->Session->setFlash($this->authError, 'default', array(), 'auth');
00343 if (!empty($controller->params['url']) && count($controller->params['url']) >= 2) {
00344 $query = $controller->params['url'];
00345 unset($query['url'], $query['ext']);
00346 $url .= Router::queryString($query, array());
00347 }
00348 $this->Session->write('Auth.redirect', $url);
00349 $controller->redirect($loginAction);
00350 return false;
00351 } elseif (!empty($this->ajaxLogin)) {
00352 $controller->viewPath = 'elements';
00353 echo $controller->render($this->ajaxLogin, $this->RequestHandler->ajaxLayout);
00354 $this->_stop();
00355 return false;
00356 } else {
00357 $controller->redirect(null, 403);
00358 }
00359 }
00360 }
00361
00362 if (!$this->authorize) {
00363 return true;
00364 }
00365
00366 extract($this->__authType());
00367 switch ($type) {
00368 case 'controller':
00369 $this->object =& $controller;
00370 break;
00371 case 'crud':
00372 case 'actions':
00373 if (isset($controller->Acl)) {
00374 $this->Acl =& $controller->Acl;
00375 } else {
00376 $err = 'Could not find AclComponent. Please include Acl in ';
00377 $err .= 'Controller::$components.';
00378 trigger_error(__($err, true), E_USER_WARNING);
00379 }
00380 break;
00381 case 'model':
00382 if (!isset($object)) {
00383 $hasModel = (
00384 isset($controller->{$controller->modelClass}) &&
00385 is_object($controller->{$controller->modelClass})
00386 );
00387 $isUses = (
00388 !empty($controller->uses) && isset($controller->{$controller->uses[0]}) &&
00389 is_object($controller->{$controller->uses[0]})
00390 );
00391
00392 if ($hasModel) {
00393 $object = $controller->modelClass;
00394 } elseif ($isUses) {
00395 $object = $controller->uses[0];
00396 }
00397 }
00398 $type = array('model' => $object);
00399 break;
00400 }
00401
00402 if ($this->isAuthorized($type)) {
00403 return true;
00404 }
00405
00406 $this->Session->setFlash($this->authError, 'default', array(), 'auth');
00407 $controller->redirect($controller->referer(), null, true);
00408 return false;
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418 function __setDefaults() {
00419 if (empty($this->userModel)) {
00420 trigger_error(__("Could not find \$userModel. Please set AuthComponent::\$userModel in beforeFilter().", true), E_USER_WARNING);
00421 return false;
00422 }
00423 $defaults = array(
00424 'loginAction' => Router::normalize(array(
00425 'controller'=> Inflector::underscore(Inflector::pluralize($this->userModel)),
00426 'action' => 'login'
00427 )),
00428 'sessionKey' => 'Auth.' . $this->userModel,
00429 'logoutRedirect' => $this->loginAction,
00430 'loginError' => __('Login failed. Invalid username or password.', true),
00431 'authError' => __('You are not authorized to access that location.', true)
00432 );
00433 foreach ($defaults as $key => $value) {
00434 if (empty($this->{$key})) {
00435 $this->{$key} = $value;
00436 }
00437 }
00438 return true;
00439 }
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461 function isAuthorized($type = null, $object = null, $user = null) {
00462 if (empty($user) && !$this->user()) {
00463 return false;
00464 } elseif (empty($user)) {
00465 $user = $this->user();
00466 }
00467
00468 extract($this->__authType($type));
00469
00470 if (!$object) {
00471 $object = $this->object;
00472 }
00473
00474 $valid = false;
00475 switch ($type) {
00476 case 'controller':
00477 $valid = $object->isAuthorized();
00478 break;
00479 case 'actions':
00480 $valid = $this->Acl->check($user, $this->action());
00481 break;
00482 case 'crud':
00483 $this->mapActions();
00484 if (!isset($this->actionMap[$this->params['action']])) {
00485 $err = 'Auth::startup() - Attempted access of un-mapped action "%1$s" in';
00486 $err .= ' controller "%2$s"';
00487 trigger_error(
00488 sprintf(__($err, true), $this->params['action'], $this->params['controller']),
00489 E_USER_WARNING
00490 );
00491 } else {
00492 $valid = $this->Acl->check(
00493 $user,
00494 $this->action(':controller'),
00495 $this->actionMap[$this->params['action']]
00496 );
00497 }
00498 break;
00499 case 'model':
00500 $this->mapActions();
00501 $action = $this->params['action'];
00502 if (isset($this->actionMap[$action])) {
00503 $action = $this->actionMap[$action];
00504 }
00505 if (is_string($object)) {
00506 $object = $this->getModel($object);
00507 }
00508 case 'object':
00509 if (!isset($action)) {
00510 $action = $this->action(':action');
00511 }
00512 if (empty($object)) {
00513 trigger_error(sprintf(__('Could not find %s. Set AuthComponent::$object in beforeFilter() or pass a valid object', true), get_class($object)), E_USER_WARNING);
00514 return;
00515 }
00516 if (method_exists($object, 'isAuthorized')) {
00517 $valid = $object->isAuthorized($user, $this->action(':controller'), $action);
00518 } elseif ($object) {
00519 trigger_error(sprintf(__('%s::isAuthorized() is not defined.', true), get_class($object)), E_USER_WARNING);
00520 }
00521 break;
00522 case null:
00523 case false:
00524 return true;
00525 break;
00526 default:
00527 trigger_error(__('Auth::isAuthorized() - $authorize is set to an incorrect value. Allowed settings are: "actions", "crud", "model" or null.', true), E_USER_WARNING);
00528 break;
00529 }
00530 return $valid;
00531 }
00532
00533
00534
00535
00536
00537
00538
00539 function __authType($auth = null) {
00540 if ($auth == null) {
00541 $auth = $this->authorize;
00542 }
00543 $object = null;
00544 if (is_array($auth)) {
00545 $type = key($auth);
00546 $object = $auth[$type];
00547 } else {
00548 $type = $auth;
00549 return compact('type');
00550 }
00551 return compact('type', 'object');
00552 }
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 function allow() {
00564 $args = func_get_args();
00565 if (empty($args) || $args == array('*')) {
00566 $this->allowedActions = $this->_methods;
00567 } else {
00568 if (isset($args[0]) && is_array($args[0])) {
00569 $args = $args[0];
00570 }
00571 $this->allowedActions = array_merge($this->allowedActions, $args);
00572 }
00573 }
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584 function deny() {
00585 $args = func_get_args();
00586 foreach ($args as $arg) {
00587 $i = array_search($arg, $this->allowedActions);
00588 if (is_int($i)) {
00589 unset($this->allowedActions[$i]);
00590 }
00591 }
00592 $this->allowedActions = array_values($this->allowedActions);
00593 }
00594
00595
00596
00597
00598
00599
00600
00601 function mapActions($map = array()) {
00602 $crud = array('create', 'read', 'update', 'delete');
00603 foreach ($map as $action => $type) {
00604 if (in_array($action, $crud) && is_array($type)) {
00605 foreach ($type as $typedAction) {
00606 $this->actionMap[$typedAction] = $action;
00607 }
00608 } else {
00609 $this->actionMap[$action] = $type;
00610 }
00611 }
00612 }
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625 function login($data = null) {
00626 $this->__setDefaults();
00627 $this->_loggedIn = false;
00628
00629 if (empty($data)) {
00630 $data = $this->data;
00631 }
00632
00633 if ($user = $this->identify($data)) {
00634 $this->Session->write($this->sessionKey, $user);
00635 $this->_loggedIn = true;
00636 }
00637 return $this->_loggedIn;
00638 }
00639
00640
00641
00642
00643
00644
00645
00646
00647 function logout() {
00648 $this->__setDefaults();
00649 $this->Session->del($this->sessionKey);
00650 $this->Session->del('Auth.redirect');
00651 $this->_loggedIn = false;
00652 return Router::normalize($this->logoutRedirect);
00653 }
00654
00655
00656
00657
00658
00659
00660
00661 function user($key = null) {
00662 $this->__setDefaults();
00663 if (!$this->Session->check($this->sessionKey)) {
00664 return null;
00665 }
00666
00667 if ($key == null) {
00668 return array($this->userModel => $this->Session->read($this->sessionKey));
00669 } else {
00670 $user = $this->Session->read($this->sessionKey);
00671 if (isset($user[$key])) {
00672 return $user[$key];
00673 }
00674 return null;
00675 }
00676 }
00677
00678
00679
00680
00681
00682
00683
00684 function redirect($url = null) {
00685 if (!is_null($url)) {
00686 $redir = $url;
00687 $this->Session->write('Auth.redirect', $redir);
00688 } elseif ($this->Session->check('Auth.redirect')) {
00689 $redir = $this->Session->read('Auth.redirect');
00690 $this->Session->delete('Auth.redirect');
00691
00692 if (Router::normalize($redir) == Router::normalize($this->loginAction)) {
00693 $redir = $this->loginRedirect;
00694 }
00695 } else {
00696 $redir = $this->loginRedirect;
00697 }
00698 return Router::normalize($redir);
00699 }
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713 function validate($object, $user = null, $action = null) {
00714 if (empty($user)) {
00715 $user = $this->user();
00716 }
00717 if (empty($user)) {
00718 return false;
00719 }
00720 return $this->Acl->check($user, $object, $action);
00721 }
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731 function action($action = ':controller/:action') {
00732 return str_replace(
00733 array(':controller', ':action'),
00734 array(Inflector::camelize($this->params['controller']), $this->params['action']),
00735 $this->actionPath . $action
00736 );
00737 }
00738
00739
00740
00741
00742
00743
00744
00745
00746 function &getModel($name = null) {
00747 $model = null;
00748 if (!$name) {
00749 $name = $this->userModel;
00750 }
00751
00752 if (PHP5) {
00753 $model = ClassRegistry::init($name);
00754 } else {
00755 $model =& ClassRegistry::init($name);
00756 }
00757
00758 if (empty($model)) {
00759 trigger_error(__('Auth::getModel() - Model is not set or could not be found', true), E_USER_WARNING);
00760 return null;
00761 }
00762
00763 return $model;
00764 }
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774 function identify($user = null, $conditions = null) {
00775 if ($conditions === false) {
00776 $conditions = null;
00777 } elseif (is_array($conditions)) {
00778 $conditions = array_merge((array)$this->userScope, $conditions);
00779 } else {
00780 $conditions = $this->userScope;
00781 }
00782 if (empty($user)) {
00783 $user = $this->user();
00784 if (empty($user)) {
00785 return null;
00786 }
00787 } elseif (is_object($user) && is_a($user, 'Model')) {
00788 if (!$user->exists()) {
00789 return null;
00790 }
00791 $user = $user->read();
00792 $user = $user[$this->userModel];
00793 } elseif (is_array($user) && isset($user[$this->userModel])) {
00794 $user = $user[$this->userModel];
00795 }
00796
00797 if (is_array($user) && (isset($user[$this->fields['username']]) || isset($user[$this->userModel . '.' . $this->fields['username']]))) {
00798
00799 if (isset($user[$this->fields['username']]) && !empty($user[$this->fields['username']]) && !empty($user[$this->fields['password']])) {
00800 if (trim($user[$this->fields['username']]) == '=' || trim($user[$this->fields['password']]) == '=') {
00801 return false;
00802 }
00803 $find = array(
00804 $this->userModel.'.'.$this->fields['username'] => $user[$this->fields['username']],
00805 $this->userModel.'.'.$this->fields['password'] => $user[$this->fields['password']]
00806 );
00807 } elseif (isset($user[$this->userModel . '.' . $this->fields['username']]) && !empty($user[$this->userModel . '.' . $this->fields['username']])) {
00808 if (trim($user[$this->userModel . '.' . $this->fields['username']]) == '=' || trim($user[$this->userModel . '.' . $this->fields['password']]) == '=') {
00809 return false;
00810 }
00811 $find = array(
00812 $this->userModel.'.'.$this->fields['username'] => $user[$this->userModel . '.' . $this->fields['username']],
00813 $this->userModel.'.'.$this->fields['password'] => $user[$this->userModel . '.' . $this->fields['password']]
00814 );
00815 } else {
00816 return false;
00817 }
00818 $model =& $this->getModel();
00819 $data = $model->find(array_merge($find, $conditions), null, null, 0);
00820 if (empty($data) || empty($data[$this->userModel])) {
00821 return null;
00822 }
00823 } elseif (!empty($user) && is_string($user)) {
00824 $model =& $this->getModel();
00825 $data = $model->find(array_merge(array($model->escapeField() => $user), $conditions));
00826
00827 if (empty($data) || empty($data[$this->userModel])) {
00828 return null;
00829 }
00830 }
00831
00832 if (!empty($data)) {
00833 if (!empty($data[$this->userModel][$this->fields['password']])) {
00834 unset($data[$this->userModel][$this->fields['password']]);
00835 }
00836 return $data[$this->userModel];
00837 }
00838 return null;
00839 }
00840
00841
00842
00843
00844
00845
00846
00847 function hashPasswords($data) {
00848 if (is_object($this->authenticate) && method_exists($this->authenticate, 'hashPasswords')) {
00849 return $this->authenticate->hashPasswords($data);
00850 }
00851
00852 if (is_array($data) && isset($data[$this->userModel])) {
00853 if (isset($data[$this->userModel][$this->fields['username']]) && isset($data[$this->userModel][$this->fields['password']])) {
00854 $data[$this->userModel][$this->fields['password']] = $this->password($data[$this->userModel][$this->fields['password']]);
00855 }
00856 }
00857 return $data;
00858 }
00859
00860
00861
00862
00863
00864
00865
00866 function password($password) {
00867 return Security::hash($password, null, true);
00868 }
00869
00870
00871
00872
00873
00874
00875 function shutdown(&$controller) {
00876 if ($this->_loggedIn) {
00877 $this->Session->del('Auth.redirect');
00878 }
00879 }
00880 }
00881 ?>