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