From 97a8c8dbd0c6e107c75c3eaee3633551265e84cb Mon Sep 17 00:00:00 2001 From: xue <> Date: Sun, 20 Nov 2005 15:55:59 +0000 Subject: --- framework/Exceptions/TErrorHandler.php | 17 ++-- framework/Exceptions/exception-en.html | 3 + framework/Exceptions/exception-zh.html | 3 + framework/Exceptions/exception.html | 3 + framework/Exceptions/messages.txt | 6 ++ framework/Security/TAuthManager.php | 175 +++++++++++++++++++++++++-------- framework/Security/TUserManager.php | 12 +-- 7 files changed, 168 insertions(+), 51 deletions(-) diff --git a/framework/Exceptions/TErrorHandler.php b/framework/Exceptions/TErrorHandler.php index 69166561..e9ef1f33 100644 --- a/framework/Exceptions/TErrorHandler.php +++ b/framework/Exceptions/TErrorHandler.php @@ -59,6 +59,10 @@ class TErrorHandler extends TComponent implements IModule * exception template file basename */ const EXCEPTION_FILE_NAME='exception'; + /** + * number of lines to be displayed in case of an exception + */ + const SOURCE_LINES=12; /** * @var string module ID @@ -223,6 +227,7 @@ class TErrorHandler extends TComponent implements IModule } } + /** * Displays exception information. * Exceptions are displayed with rich context information, including @@ -234,19 +239,19 @@ class TErrorHandler extends TComponent implements IModule { $lines=file($exception->getFile()); $errorLine=$exception->getLine(); - $beginLine=$errorLine-9>=0?$errorLine-9:0; - $endLine=$errorLine+8<=count($lines)?$errorLine+8:count($lines); + $beginLine=$errorLine-self::SOURCE_LINES>=0?$errorLine-self::SOURCE_LINES:0; + $endLine=$errorLine+self::SOURCE_LINES<=count($lines)?$errorLine+self::SOURCE_LINES:count($lines); $source=''; - for($i=$beginLine;$i<$endLine;++$i) + for($i=$beginLine-1;$i<$endLine;++$i) { if($i===$errorLine-1) { - $line=highlight_string(sprintf("Line %4d: %s",$i+1,$lines[$i]),true); - $source.="
".$line."
"; + $line=htmlspecialchars(sprintf("%04d: %s",$i+1,str_replace("\t",' ',$lines[$i]))); + $source.="
".$line."
"; } else - $source.=highlight_string(sprintf("Line %4d: %s",$i+1,$lines[$i]),true); + $source.=htmlspecialchars(sprintf("%04d: %s",$i+1,str_replace("\t",' ',$lines[$i]))); } $fields=array( diff --git a/framework/Exceptions/exception-en.html b/framework/Exceptions/exception-en.html index 1d76c7f2..67e15dfe 100644 --- a/framework/Exceptions/exception-en.html +++ b/framework/Exceptions/exception-en.html @@ -10,6 +10,7 @@ p {font-family:"Verdana";font-weight:normal;color:black;font-size:9pt;margin-top code,pre {font-family:"Lucida Console";} td,.version {color: gray;font-size:8pt;border-top:1px solid #aaaaaa;} .source {font-family:"Lucida Console";font-weight:normal;background-color:#ffffee;} +.error {background-color: #ffeeee;} @@ -21,7 +22,9 @@ td,.version {color: gray;font-size:8pt;border-top:1px solid #aaaaaa;}

Source File

%%SourceFile%%

+
 %%SourceCode%%
+

Stack Trace

diff --git a/framework/Exceptions/exception-zh.html b/framework/Exceptions/exception-zh.html index 8f56ec9e..e0897688 100644 --- a/framework/Exceptions/exception-zh.html +++ b/framework/Exceptions/exception-zh.html @@ -10,6 +10,7 @@ p {font-family:"Verdana";font-weight:normal;color:black;font-size:9pt;margin-top code,pre {font-family:"Lucida Console";} td,.version {color: gray;font-size:8pt;border-top:1px solid #aaaaaa;} .source {font-family:"Lucida Console";font-weight:normal;background-color:#ffffee;} +.error {background-color: #ffeeee;} @@ -21,7 +22,9 @@ td,.version {color: gray;font-size:8pt;border-top:1px solid #aaaaaa;}

错误代码文件

%%SourceFile%%

+
 %%SourceCode%%
+

错误堆栈信息

diff --git a/framework/Exceptions/exception.html b/framework/Exceptions/exception.html index 1d76c7f2..67e15dfe 100644 --- a/framework/Exceptions/exception.html +++ b/framework/Exceptions/exception.html @@ -10,6 +10,7 @@ p {font-family:"Verdana";font-weight:normal;color:black;font-size:9pt;margin-top code,pre {font-family:"Lucida Console";} td,.version {color: gray;font-size:8pt;border-top:1px solid #aaaaaa;} .source {font-family:"Lucida Console";font-weight:normal;background-color:#ffffee;} +.error {background-color: #ffeeee;} @@ -21,7 +22,9 @@ td,.version {color: gray;font-size:8pt;border-top:1px solid #aaaaaa;}

Source File

%%SourceFile%%

+
 %%SourceCode%%
+

Stack Trace

diff --git a/framework/Exceptions/messages.txt b/framework/Exceptions/messages.txt index 49160370..209c0124 100644 --- a/framework/Exceptions/messages.txt +++ b/framework/Exceptions/messages.txt @@ -79,6 +79,12 @@ xmldocument_file_write_failed = TXmlDocument is unable to write file '%s'. authorizationrule_action_invalid = TAuthorizationRule.Action can only take 'allow' or 'deny' as the value. authorizationrule_verb_invalid = TAuthorizationRule.Verb can only take 'get' or 'post' as the value. +authmanager_usermanager_required = TAuthManager.UserManager must be assigned a value. +authmanager_usermanager_inexistent = TAuthManager.UserManager '%s' does not refer to an ID of application module. +authmanager_usermanager_invalid = TAuthManager.UserManager '%s' does not refer to a valid TUserManager application module. +authmanager_usermanager_unchangeable = TAuthManager.UserManager cannot be modified after the module is initialized. +authmanager_session_required = TAuthManager requires a session application module. + body_contents_not_allowed = %s: body contents are not allowed. control_id_not_unique = Control ID '%s' is not unique for control type '%s'. control_not_found = Unable to find a control with ID '%s'. diff --git a/framework/Security/TAuthManager.php b/framework/Security/TAuthManager.php index 32b68cdd..f24a1bdd 100644 --- a/framework/Security/TAuthManager.php +++ b/framework/Security/TAuthManager.php @@ -10,27 +10,55 @@ * @package System.Security */ +/** + * Using TUserManager class + */ +Prado::using('System.Security.TUserManager'); + /** * TAuthManager class * * TAuthManager performs user authentication and authorization for a Prado application. + * TAuthManager works together with a {@link TUserManager} module that can be + * specified via the {@link setUserManager UserManager} property. + * If an authorization fails, TAuthManager will try to redirect the client + * browser to a login page that is specified via the {@link setLoginPage LoginPage}. + * To login or logout a user, call {@link login} or {@link logout}, respectively. * + * To load TAuthManager, configure it in application configuration as follows, + * + * * * @author Qiang Xue * @version $Revision: $ $Date: $ * @package System.Security * @since 3.0 */ - -Prado::using('System.Security.TUserManager'); - class TAuthManager extends TComponent implements IModule { + /** + * GET variable name for return url + */ const RETURN_URL_VAR='ReturnUrl'; + /** + * @var boolean if the module has been initialized + */ private $_initialized=false; + /** + * @var TApplication application instance + */ private $_application; - private $_users=null; + /** + * @var TUserManager user manager instance + */ + private $_userManager=null; + /** + * @var string login page + */ private $_loginPage=null; + /** + * @var boolean whether authorization should be skipped + */ private $_skipAuthorization=false; /** @@ -54,9 +82,20 @@ class TAuthManager extends TComponent implements IModule * This method is required by the IModule interface. * @param TApplication Prado application, can be null * @param TXmlElement configuration for this module, can be null + * @throws TConfigurationException if user manager does not exist or is not TUserManager */ public function init($application,$config) { + if($this->_userManager===null) + throw new TConfigurationException('authmanager_usermanager_required'); + if(is_string($this->_userManager)) + { + if(($users=$application->getModule($this->_userManager))===null) + throw new TConfigurationException('authmanager_usermanager_inexistent',$this->_userManager); + if(!($users instanceof TUserManager)) + throw new TConfigurationException('authmanager_usermanager_invalid',$this->_userManager); + $this->_userManager=$users; + } $this->_application=$application; $application->attachEventHandler('Authentication',array($this,'doAuthentication')); $application->attachEventHandler('EndRequest',array($this,'leave')); @@ -64,36 +103,53 @@ class TAuthManager extends TComponent implements IModule $this->_initialized=true; } + /** + * @return TUserManager user manager instance + */ public function getUserManager() { - if($this->_users instanceof TUserManager) - return $this->_users; - else - { - if(($users=$this->_application->getModule($this->_users))===null) - throw new TConfigurationException('authenticator_usermanager_inexistent',$this->_users); - if(!($users instanceof TUserManager)) - throw new TConfigurationException('authenticator_usermanager_invalid',$this->_users); - $this->_users=$users; - return $users; - } + return $this->_userManager; } + /** + * @param string|TUserManager the user manager module ID or the user mananger object + * @throws TInvalidOperationException if the module has been initialized or the user manager object is not TUserManager + */ public function setUserManager($provider) { - $this->_users=$provider; + if($this->_initialized) + throw new TInvalidOperationException('authmanager_usermanager_unchangeable'); + if(!is_string($provider) && !($provider instanceof TUserManager)) + throw new TConfigurationException('authmanager_usermanager_invalid',$this->_userManager); + $this->_userManager=$provider; } + /** + * @return string path of login page should login is required + */ public function getLoginPage() { return $this->_loginPage; } + /** + * Sets the login page that the client browser will be redirected to if login is needed. + * Login page should be specified in the format of page path. + * @param string path of login page should login is required + * @see TPageService + */ public function setLoginPage($pagePath) { $this->_loginPage=$pagePath; } + /** + * Performs authentication. + * This is the event handler attached to application's Authentication event. + * Do not call this method directly. + * @param mixed sender of the Authentication event + * @param mixed event parameter + */ public function doAuthentication($sender,$param) { $this->onAuthenticate($param); @@ -103,6 +159,13 @@ class TAuthManager extends TComponent implements IModule $this->_skipAuthorization=true; } + /** + * Performs authorization. + * This is the event handler attached to application's Authorization event. + * Do not call this method directly. + * @param mixed sender of the Authorization event + * @param mixed event parameter + */ public function doAuthorization($sender,$param) { if(!$this->_skipAuthorization) @@ -111,6 +174,13 @@ class TAuthManager extends TComponent implements IModule } } + /** + * Performs login redirect if authorization fails. + * This is the event handler attached to application's EndRequest event. + * Do not call this method directly. + * @param mixed sender of the event + * @param mixed event parameter + */ public function leave($sender,$param) { if($this->_application->getResponse()->getStatusCode()===401) @@ -125,6 +195,14 @@ class TAuthManager extends TComponent implements IModule } } + /** + * Performs the real authentication work. + * An Authenticate event will be raised if there is any handler attached to it. + * If the application already has a non-null user, it will return without further authentication. + * Otherwise, user information will be restored from session data. + * @param mixed parameter to be passed to Authenticate event + * @throws TConfigurationException if session module does not exist. + */ public function onAuthenticate($param) { if($this->hasEventHandler('Authenticate')) @@ -133,18 +211,23 @@ class TAuthManager extends TComponent implements IModule return; if(($session=$this->_application->getSession())===null) - throw new TConfigurationException('authenticator_session_required'); + throw new TConfigurationException('authmanager_session_required'); $session->open(); - if(($userManager=$this->getUserManager())===null) - throw new TConfigurationException('authenticator_usermanager_required'); $sessionInfo=$session->getItems()->itemAt($this->generateUserSessionKey()); - $user=$userManager->getUser(null)->loadFromString($sessionInfo); + $user=$this->_userManager->getUser(null)->loadFromString($sessionInfo); $this->_application->setUser($user); } + /** + * Performs the real authorization work. + * Authorization rules obtained from the application will be used to check + * if a user is allowed. If authorization fails, the response status code + * will be set as 401 and the application terminates. + * @param mixed parameter to be passed to Authenticate event + */ public function onAuthorize($param) { - if($this->hasEventHandler('Authenticate')) + if($this->hasEventHandler('Authorize')) $this->raiseEvent('Authorize',$this,$this->_application); if(!$this->_application->getAuthorizationRules()->isUserAllowed($this->_application->getUser(),$this->_application->getRequest()->getRequestType())) { @@ -153,49 +236,63 @@ class TAuthManager extends TComponent implements IModule } } + /** + * @return string a key used to store user information in session + */ protected function generateUserSessionKey() { return md5($this->_application->getUniqueID().'prado:user'); } + /** + * Updates the user data stored in session. + * @param IUser user object + * @throws new TConfigurationException if session module is not loaded. + */ public function updateSessionUser($user) { if(!$user->getIsGuest()) { if(($session=$this->_application->getSession())===null) - throw new TConfigurationException('authenticator_session_required'); + throw new TConfigurationException('authmanager_session_required'); else $session->getItems()->add($this->generateUserSessionKey(),$user->saveToString()); } } + /** + * Logs in a user with username and password. + * The username and password will be used to validate if login is successful. + * If yes, a user object will be created for the application. + * @param string username + * @param string password + * @return boolean if login is successful + */ public function login($username,$password) { - if(($userManager=$this->getUserManager())===null) - throw new TConfigurationException('authenticator_usermanager_required'); - else + if($this->_userManager->validateUser($username,$password)) { - if($userManager->validateUser($username,$password)) - { - $user=$userManager->getUser($username); - $this->updateSessionUser($user); - $this->_application->setUser($user); - return true; - } - else - return false; + $user=$this->_userManager->getUser($username); + $this->updateSessionUser($user); + $this->_application->setUser($user); + return true; } + else + return false; } + /** + * Logs out a user. + * User session will be destroyed after this method is called. + * @throws TConfigurationException if session module is not loaded. + */ public function logout() { - if(($userManager=$this->getUserManager())===null) - throw new TConfigurationException('authenticator_usermanager_required'); - else if(($session=$this->_application->getSession())===null) - throw new TConfigurationException('authenticator_session_required'); + if(($session=$this->_application->getSession())===null) + throw new TConfigurationException('authmanager_session_required'); else { - $userManager->switchToGuest($this->_application->getUser()); + $this->_userManager->switchToGuest($this->_application->getUser()); $session->destroy(); } } diff --git a/framework/Security/TUserManager.php b/framework/Security/TUserManager.php index c4bcbacd..9da386f0 100644 --- a/framework/Security/TUserManager.php +++ b/framework/Security/TUserManager.php @@ -169,12 +169,12 @@ class TUser extends TComponent implements IUser * * TUserManager manages a static list of users {@link TUser}. * The user information is specified via module configuration using the following XML syntax, - * - * - * - * - * - * + * + * + * + * + * + * * * The user passwords may be specified as clear text, SH1 or MD5 hashed by setting * {@link setPasswordMode PasswordMode} as Clear, SH1 or MD5. -- cgit v1.2.3