diff options
author | ctrlaltca <> | 2012-07-12 11:21:01 +0000 |
---|---|---|
committer | ctrlaltca <> | 2012-07-12 11:21:01 +0000 |
commit | 903ae8a581fac1e6917fc3e31d2ad8fb91df80c3 (patch) | |
tree | e08bf04f0823650a231227ac3499121270172a23 /framework/Security | |
parent | 3e4e6e66aeb3f8fea4e1eb4237498ef9d2358f63 (diff) |
standardize the use of unix eol; use svn properties to enforce native eol
Diffstat (limited to 'framework/Security')
-rw-r--r-- | framework/Security/IUserManager.php | 114 | ||||
-rw-r--r-- | framework/Security/TAuthManager.php | 914 | ||||
-rw-r--r-- | framework/Security/TAuthorizationRule.php | 590 | ||||
-rw-r--r-- | framework/Security/TDbUserManager.php | 638 | ||||
-rw-r--r-- | framework/Security/TUser.php | 442 | ||||
-rw-r--r-- | framework/Security/TUserManager.php | 802 |
6 files changed, 1750 insertions, 1750 deletions
diff --git a/framework/Security/IUserManager.php b/framework/Security/IUserManager.php index 2769db8f..19431bd9 100644 --- a/framework/Security/IUserManager.php +++ b/framework/Security/IUserManager.php @@ -1,58 +1,58 @@ -<?php
-/**
- * IUserManager interface file
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
+<?php +/** + * IUserManager interface file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Security
- */
-
-/**
- * IUserManager interface
- *
- * IUserManager specifies the interface that must be implemented by
- * a user manager class if it is to be used together with {@link TAuthManager}
- * and {@link TUser}.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Security
- * @since 3.0
- */
-interface IUserManager
-{
- /**
- * @return string name for a guest user.
- */
- public function getGuestName();
- /**
- * Returns a user instance given the user name.
- * @param string user name, null if it is a guest.
- * @return TUser the user instance, null if the specified username is not in the user database.
- */
- public function getUser($username=null);
- /**
- * Returns a user instance according to auth data stored in a cookie.
- * @param THttpCookie the cookie storing user authentication information
- * @return TUser the user instance generated based on the cookie auth data, null if the cookie does not have valid auth data.
- * @since 3.1.1
- */
- public function getUserFromCookie($cookie);
- /**
- * Saves user auth data into a cookie.
- * @param THttpCookie the cookie to receive the user auth data.
- * @since 3.1.1
- */
- public function saveUserToCookie($cookie);
- /**
- * Validates if the username and password are correct.
- * @param string user name
- * @param string password
- * @return boolean true if validation is successful, false otherwise.
- */
- public function validateUser($username,$password);
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Security + */ + +/** + * IUserManager interface + * + * IUserManager specifies the interface that must be implemented by + * a user manager class if it is to be used together with {@link TAuthManager} + * and {@link TUser}. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Security + * @since 3.0 + */ +interface IUserManager +{ + /** + * @return string name for a guest user. + */ + public function getGuestName(); + /** + * Returns a user instance given the user name. + * @param string user name, null if it is a guest. + * @return TUser the user instance, null if the specified username is not in the user database. + */ + public function getUser($username=null); + /** + * Returns a user instance according to auth data stored in a cookie. + * @param THttpCookie the cookie storing user authentication information + * @return TUser the user instance generated based on the cookie auth data, null if the cookie does not have valid auth data. + * @since 3.1.1 + */ + public function getUserFromCookie($cookie); + /** + * Saves user auth data into a cookie. + * @param THttpCookie the cookie to receive the user auth data. + * @since 3.1.1 + */ + public function saveUserToCookie($cookie); + /** + * Validates if the username and password are correct. + * @param string user name + * @param string password + * @return boolean true if validation is successful, false otherwise. + */ + public function validateUser($username,$password); +} + diff --git a/framework/Security/TAuthManager.php b/framework/Security/TAuthManager.php index 92836195..6a774a8e 100644 --- a/framework/Security/TAuthManager.php +++ b/framework/Security/TAuthManager.php @@ -1,457 +1,457 @@ -<?php
-/**
- * TAuthManager class file
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2012 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Security
- */
-
-/**
- * Using IUserManager interface
- */
-Prado::using('System.Security.IUserManager');
-
-/**
- * TAuthManager class
- *
- * TAuthManager performs user authentication and authorization for a Prado application.
- * TAuthManager works together with a {@link IUserManager} 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.
- *
- * The {@link setAuthExpire AuthExpire} property can be used to define the time
- * in seconds after which the authentication should expire.
- * {@link setAllowAutoLogin AllowAutoLogin} specifies if the login information
- * should be stored in a cookie to perform automatic login. Enabling this
- * feature will cause that {@link setAuthExpire AuthExpire} has no effect
- * since the user will be logged in again on authentication expiration.
- *
- * To load TAuthManager, configure it in application configuration as follows,
- * <module id="auth" class="System.Security.TAuthManager" UserManager="users" LoginPage="login" />
- * <module id="users" class="System.Security.TUserManager" />
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Security
- * @since 3.0
- */
-class TAuthManager extends TModule
-{
- /**
- * GET variable name for return url
- */
- const RETURN_URL_VAR='ReturnUrl';
- /**
- * @var boolean if the module has been initialized
- */
- private $_initialized=false;
- /**
- * @var IUserManager user manager instance
- */
- private $_userManager;
- /**
- * @var string login page
- */
- private $_loginPage;
- /**
- * @var boolean whether authorization should be skipped
- */
- private $_skipAuthorization=false;
- /**
- * @var string the session var name for storing return URL
- */
- private $_returnUrlVarName;
- /**
- * @var boolean whether to allow auto login (using cookie)
- */
- private $_allowAutoLogin=false;
- /**
- * @var string variable name used to store user session or cookie
- */
- private $_userKey;
- /**
- * @var integer authentication expiration time in seconds. Defaults to zero (no expiration)
- */
- private $_authExpire=0;
-
- /**
- * Initializes this module.
- * This method is required by the IModule interface.
- * @param TXmlElement configuration for this module, can be null
- * @throws TConfigurationException if user manager does not exist or is not IUserManager
- */
- public function init($config)
- {
- if($this->_userManager===null)
- throw new TConfigurationException('authmanager_usermanager_required');
- if($this->_returnUrlVarName===null)
- $this->_returnUrlVarName=$this->getApplication()->getID().':'.self::RETURN_URL_VAR;
- $application=$this->getApplication();
- if(is_string($this->_userManager))
- {
- if(($users=$application->getModule($this->_userManager))===null)
- throw new TConfigurationException('authmanager_usermanager_inexistent',$this->_userManager);
- if(!($users instanceof IUserManager))
- throw new TConfigurationException('authmanager_usermanager_invalid',$this->_userManager);
- $this->_userManager=$users;
- }
- $application->attachEventHandler('OnAuthentication',array($this,'doAuthentication'));
- $application->attachEventHandler('OnEndRequest',array($this,'leave'));
- $application->attachEventHandler('OnAuthorization',array($this,'doAuthorization'));
- $this->_initialized=true;
- }
-
- /**
- * @return IUserManager user manager instance
- */
- public function getUserManager()
- {
- return $this->_userManager;
- }
-
- /**
- * @param string|IUserManager the user manager module ID or the user manager object
- * @throws TInvalidOperationException if the module has been initialized or the user manager object is not IUserManager
- */
- public function setUserManager($provider)
- {
- if($this->_initialized)
- throw new TInvalidOperationException('authmanager_usermanager_unchangeable');
- if(!is_string($provider) && !($provider instanceof IUserManager))
- 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);
-
- $service=$this->getService();
- if(($service instanceof TPageService) && $service->getRequestedPagePath()===$this->getLoginPage())
- $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)
- {
- $this->onAuthorize($param);
- }
- }
-
- /**
- * 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)
- {
- $application=$this->getApplication();
- if($application->getResponse()->getStatusCode()===401)
- {
- $service=$application->getService();
- if($service instanceof TPageService)
- {
- $returnUrl=$application->getRequest()->getRequestUri();
- $this->setReturnUrl($returnUrl);
- $url=$service->constructUrl($this->getLoginPage());
- $application->getResponse()->redirect($url);
- }
- }
- }
-
- /**
- * @return string the name of the session variable storing return URL. It defaults to 'AppID:ReturnUrl'
- */
- public function getReturnUrlVarName()
- {
- return $this->_returnUrlVarName;
- }
-
- /**
- * @param string the name of the session variable storing return URL.
- */
- public function setReturnUrlVarName($value)
- {
- $this->_returnUrlVarName=$value;
- }
-
- /**
- * @return string URL that the browser should be redirected to when login succeeds.
- */
- public function getReturnUrl()
- {
- return $this->getSession()->itemAt($this->getReturnUrlVarName());
- }
-
- /**
- * Sets the URL that the browser should be redirected to when login succeeds.
- * @param string the URL to be redirected to.
- */
- public function setReturnUrl($value)
- {
- $this->getSession()->add($this->getReturnUrlVarName(),$value);
- }
-
- /**
- * @return boolean whether to allow remembering login so that the user logs on automatically next time. Defaults to false.
- * @since 3.1.1
- */
- public function getAllowAutoLogin()
- {
- return $this->_allowAutoLogin;
- }
-
- /**
- * @param boolean whether to allow remembering login so that the user logs on automatically next time. Users have to enable cookie to make use of this feature.
- * @since 3.1.1
- */
- public function setAllowAutoLogin($value)
- {
- $this->_allowAutoLogin=TPropertyValue::ensureBoolean($value);
- }
-
- /**
- * @return integer authentication expiration time in seconds. Defaults to zero (no expiration).
- * @since 3.1.3
- */
- public function getAuthExpire()
- {
- return $this->_authExpire;
- }
-
- /**
- * @param integer authentication expiration time in seconds. Defaults to zero (no expiration).
- * @since 3.1.3
- */
- public function setAuthExpire($value)
- {
- $this->_authExpire=TPropertyValue::ensureInteger($value);
- }
-
- /**
- * Performs the real authentication work.
- * An OnAuthenticate 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 OnAuthenticate event
- * @throws TConfigurationException if session module does not exist.
- */
- public function onAuthenticate($param)
- {
- $application=$this->getApplication();
-
- // restoring user info from session
- if(($session=$application->getSession())===null)
- throw new TConfigurationException('authmanager_session_required');
- $session->open();
- $sessionInfo=$session->itemAt($this->getUserKey());
- $user=$this->_userManager->getUser(null)->loadFromString($sessionInfo);
-
- // check for authentication expiration
- $isAuthExpired = $this->_authExpire>0 && !$user->getIsGuest() &&
- ($expiretime=$session->itemAt('AuthExpireTime')) && $expiretime<time();
-
- // try authenticating through cookie if possible
- if($this->getAllowAutoLogin() && ($user->getIsGuest() || $isAuthExpired))
- {
- $cookie=$this->getRequest()->getCookies()->itemAt($this->getUserKey());
- if($cookie instanceof THttpCookie)
- {
- if(($user2=$this->_userManager->getUserFromCookie($cookie))!==null)
- {
- $user=$user2;
- $this->updateSessionUser($user);
- // user is restored from cookie, auth may not expire
- $isAuthExpired = false;
- }
- }
- }
-
- $application->setUser($user);
-
- // handle authentication expiration or update expiration time
- if($isAuthExpired)
- $this->onAuthExpire($param);
- else
- $session->add('AuthExpireTime', time() + $this->_authExpire);
-
- // event handler gets a chance to do further auth work
- if($this->hasEventHandler('OnAuthenticate'))
- $this->raiseEvent('OnAuthenticate',$this,$application);
- }
-
- /**
- * Performs user logout on authentication expiration.
- * An 'OnAuthExpire' event will be raised if there is any handler attached to it.
- * @param mixed parameter to be passed to OnAuthExpire event.
- */
- public function onAuthExpire($param)
- {
- $this->logout();
- if($this->hasEventHandler('OnAuthExpire'))
- $this->raiseEvent('OnAuthExpire',$this,$param);
- }
-
- /**
- * 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 OnAuthorize event
- */
- public function onAuthorize($param)
- {
- $application=$this->getApplication();
- if($this->hasEventHandler('OnAuthorize'))
- $this->raiseEvent('OnAuthorize',$this,$application);
- if(!$application->getAuthorizationRules()->isUserAllowed($application->getUser(),$application->getRequest()->getRequestType(),$application->getRequest()->getUserHostAddress()))
- {
- $application->getResponse()->setStatusCode(401);
- $application->completeRequest();
- }
- }
-
- /**
- * @return string a unique variable name for storing user session/cookie data
- * @since 3.1.1
- */
- public function getUserKey()
- {
- if($this->_userKey===null)
- $this->_userKey=$this->generateUserKey();
- return $this->_userKey;
- }
-
- /**
- * @return string a key used to store user information in session
- * @since 3.1.1
- */
- protected function generateUserKey()
- {
- return md5($this->getApplication()->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->getSession())===null)
- throw new TConfigurationException('authmanager_session_required');
- else
- $session->add($this->getUserKey(),$user->saveToString());
- }
- }
-
- /**
- * Switches to a new user.
- * This method will logout the current user first and login with a new one (without password.)
- * @param string the new username
- * @return boolean if the switch is successful
- */
- public function switchUser($username)
- {
- if(($user=$this->_userManager->getUser($username))===null)
- return false;
- $this->updateSessionUser($user);
- $this->getApplication()->setUser($user);
- return true;
- }
-
- /**
- * 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
- * @param integer number of seconds that automatic login will remain effective. If 0, it means user logs out when session ends. This parameter is added since 3.1.1.
- * @return boolean if login is successful
- */
- public function login($username,$password,$expire=0)
- {
- if($this->_userManager->validateUser($username,$password))
- {
- if(($user=$this->_userManager->getUser($username))===null)
- return false;
- $this->updateSessionUser($user);
- $this->getApplication()->setUser($user);
-
- if($expire>0)
- {
- $cookie=new THttpCookie($this->getUserKey(),'');
- $cookie->setExpire(time()+$expire);
- $this->_userManager->saveUserToCookie($cookie);
- $this->getResponse()->getCookies()->add($cookie);
- }
- 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(($session=$this->getSession())===null)
- throw new TConfigurationException('authmanager_session_required');
- $this->getApplication()->getUser()->setIsGuest(true);
- $session->destroy();
- if($this->getAllowAutoLogin())
- {
- $cookie=new THttpCookie($this->getUserKey(),'');
- $this->getResponse()->getCookies()->add($cookie);
- }
- }
-}
-
-?>
+<?php +/** + * TAuthManager class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Security + */ + +/** + * Using IUserManager interface + */ +Prado::using('System.Security.IUserManager'); + +/** + * TAuthManager class + * + * TAuthManager performs user authentication and authorization for a Prado application. + * TAuthManager works together with a {@link IUserManager} 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. + * + * The {@link setAuthExpire AuthExpire} property can be used to define the time + * in seconds after which the authentication should expire. + * {@link setAllowAutoLogin AllowAutoLogin} specifies if the login information + * should be stored in a cookie to perform automatic login. Enabling this + * feature will cause that {@link setAuthExpire AuthExpire} has no effect + * since the user will be logged in again on authentication expiration. + * + * To load TAuthManager, configure it in application configuration as follows, + * <module id="auth" class="System.Security.TAuthManager" UserManager="users" LoginPage="login" /> + * <module id="users" class="System.Security.TUserManager" /> + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Security + * @since 3.0 + */ +class TAuthManager extends TModule +{ + /** + * GET variable name for return url + */ + const RETURN_URL_VAR='ReturnUrl'; + /** + * @var boolean if the module has been initialized + */ + private $_initialized=false; + /** + * @var IUserManager user manager instance + */ + private $_userManager; + /** + * @var string login page + */ + private $_loginPage; + /** + * @var boolean whether authorization should be skipped + */ + private $_skipAuthorization=false; + /** + * @var string the session var name for storing return URL + */ + private $_returnUrlVarName; + /** + * @var boolean whether to allow auto login (using cookie) + */ + private $_allowAutoLogin=false; + /** + * @var string variable name used to store user session or cookie + */ + private $_userKey; + /** + * @var integer authentication expiration time in seconds. Defaults to zero (no expiration) + */ + private $_authExpire=0; + + /** + * Initializes this module. + * This method is required by the IModule interface. + * @param TXmlElement configuration for this module, can be null + * @throws TConfigurationException if user manager does not exist or is not IUserManager + */ + public function init($config) + { + if($this->_userManager===null) + throw new TConfigurationException('authmanager_usermanager_required'); + if($this->_returnUrlVarName===null) + $this->_returnUrlVarName=$this->getApplication()->getID().':'.self::RETURN_URL_VAR; + $application=$this->getApplication(); + if(is_string($this->_userManager)) + { + if(($users=$application->getModule($this->_userManager))===null) + throw new TConfigurationException('authmanager_usermanager_inexistent',$this->_userManager); + if(!($users instanceof IUserManager)) + throw new TConfigurationException('authmanager_usermanager_invalid',$this->_userManager); + $this->_userManager=$users; + } + $application->attachEventHandler('OnAuthentication',array($this,'doAuthentication')); + $application->attachEventHandler('OnEndRequest',array($this,'leave')); + $application->attachEventHandler('OnAuthorization',array($this,'doAuthorization')); + $this->_initialized=true; + } + + /** + * @return IUserManager user manager instance + */ + public function getUserManager() + { + return $this->_userManager; + } + + /** + * @param string|IUserManager the user manager module ID or the user manager object + * @throws TInvalidOperationException if the module has been initialized or the user manager object is not IUserManager + */ + public function setUserManager($provider) + { + if($this->_initialized) + throw new TInvalidOperationException('authmanager_usermanager_unchangeable'); + if(!is_string($provider) && !($provider instanceof IUserManager)) + 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); + + $service=$this->getService(); + if(($service instanceof TPageService) && $service->getRequestedPagePath()===$this->getLoginPage()) + $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) + { + $this->onAuthorize($param); + } + } + + /** + * 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) + { + $application=$this->getApplication(); + if($application->getResponse()->getStatusCode()===401) + { + $service=$application->getService(); + if($service instanceof TPageService) + { + $returnUrl=$application->getRequest()->getRequestUri(); + $this->setReturnUrl($returnUrl); + $url=$service->constructUrl($this->getLoginPage()); + $application->getResponse()->redirect($url); + } + } + } + + /** + * @return string the name of the session variable storing return URL. It defaults to 'AppID:ReturnUrl' + */ + public function getReturnUrlVarName() + { + return $this->_returnUrlVarName; + } + + /** + * @param string the name of the session variable storing return URL. + */ + public function setReturnUrlVarName($value) + { + $this->_returnUrlVarName=$value; + } + + /** + * @return string URL that the browser should be redirected to when login succeeds. + */ + public function getReturnUrl() + { + return $this->getSession()->itemAt($this->getReturnUrlVarName()); + } + + /** + * Sets the URL that the browser should be redirected to when login succeeds. + * @param string the URL to be redirected to. + */ + public function setReturnUrl($value) + { + $this->getSession()->add($this->getReturnUrlVarName(),$value); + } + + /** + * @return boolean whether to allow remembering login so that the user logs on automatically next time. Defaults to false. + * @since 3.1.1 + */ + public function getAllowAutoLogin() + { + return $this->_allowAutoLogin; + } + + /** + * @param boolean whether to allow remembering login so that the user logs on automatically next time. Users have to enable cookie to make use of this feature. + * @since 3.1.1 + */ + public function setAllowAutoLogin($value) + { + $this->_allowAutoLogin=TPropertyValue::ensureBoolean($value); + } + + /** + * @return integer authentication expiration time in seconds. Defaults to zero (no expiration). + * @since 3.1.3 + */ + public function getAuthExpire() + { + return $this->_authExpire; + } + + /** + * @param integer authentication expiration time in seconds. Defaults to zero (no expiration). + * @since 3.1.3 + */ + public function setAuthExpire($value) + { + $this->_authExpire=TPropertyValue::ensureInteger($value); + } + + /** + * Performs the real authentication work. + * An OnAuthenticate 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 OnAuthenticate event + * @throws TConfigurationException if session module does not exist. + */ + public function onAuthenticate($param) + { + $application=$this->getApplication(); + + // restoring user info from session + if(($session=$application->getSession())===null) + throw new TConfigurationException('authmanager_session_required'); + $session->open(); + $sessionInfo=$session->itemAt($this->getUserKey()); + $user=$this->_userManager->getUser(null)->loadFromString($sessionInfo); + + // check for authentication expiration + $isAuthExpired = $this->_authExpire>0 && !$user->getIsGuest() && + ($expiretime=$session->itemAt('AuthExpireTime')) && $expiretime<time(); + + // try authenticating through cookie if possible + if($this->getAllowAutoLogin() && ($user->getIsGuest() || $isAuthExpired)) + { + $cookie=$this->getRequest()->getCookies()->itemAt($this->getUserKey()); + if($cookie instanceof THttpCookie) + { + if(($user2=$this->_userManager->getUserFromCookie($cookie))!==null) + { + $user=$user2; + $this->updateSessionUser($user); + // user is restored from cookie, auth may not expire + $isAuthExpired = false; + } + } + } + + $application->setUser($user); + + // handle authentication expiration or update expiration time + if($isAuthExpired) + $this->onAuthExpire($param); + else + $session->add('AuthExpireTime', time() + $this->_authExpire); + + // event handler gets a chance to do further auth work + if($this->hasEventHandler('OnAuthenticate')) + $this->raiseEvent('OnAuthenticate',$this,$application); + } + + /** + * Performs user logout on authentication expiration. + * An 'OnAuthExpire' event will be raised if there is any handler attached to it. + * @param mixed parameter to be passed to OnAuthExpire event. + */ + public function onAuthExpire($param) + { + $this->logout(); + if($this->hasEventHandler('OnAuthExpire')) + $this->raiseEvent('OnAuthExpire',$this,$param); + } + + /** + * 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 OnAuthorize event + */ + public function onAuthorize($param) + { + $application=$this->getApplication(); + if($this->hasEventHandler('OnAuthorize')) + $this->raiseEvent('OnAuthorize',$this,$application); + if(!$application->getAuthorizationRules()->isUserAllowed($application->getUser(),$application->getRequest()->getRequestType(),$application->getRequest()->getUserHostAddress())) + { + $application->getResponse()->setStatusCode(401); + $application->completeRequest(); + } + } + + /** + * @return string a unique variable name for storing user session/cookie data + * @since 3.1.1 + */ + public function getUserKey() + { + if($this->_userKey===null) + $this->_userKey=$this->generateUserKey(); + return $this->_userKey; + } + + /** + * @return string a key used to store user information in session + * @since 3.1.1 + */ + protected function generateUserKey() + { + return md5($this->getApplication()->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->getSession())===null) + throw new TConfigurationException('authmanager_session_required'); + else + $session->add($this->getUserKey(),$user->saveToString()); + } + } + + /** + * Switches to a new user. + * This method will logout the current user first and login with a new one (without password.) + * @param string the new username + * @return boolean if the switch is successful + */ + public function switchUser($username) + { + if(($user=$this->_userManager->getUser($username))===null) + return false; + $this->updateSessionUser($user); + $this->getApplication()->setUser($user); + return true; + } + + /** + * 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 + * @param integer number of seconds that automatic login will remain effective. If 0, it means user logs out when session ends. This parameter is added since 3.1.1. + * @return boolean if login is successful + */ + public function login($username,$password,$expire=0) + { + if($this->_userManager->validateUser($username,$password)) + { + if(($user=$this->_userManager->getUser($username))===null) + return false; + $this->updateSessionUser($user); + $this->getApplication()->setUser($user); + + if($expire>0) + { + $cookie=new THttpCookie($this->getUserKey(),''); + $cookie->setExpire(time()+$expire); + $this->_userManager->saveUserToCookie($cookie); + $this->getResponse()->getCookies()->add($cookie); + } + 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(($session=$this->getSession())===null) + throw new TConfigurationException('authmanager_session_required'); + $this->getApplication()->getUser()->setIsGuest(true); + $session->destroy(); + if($this->getAllowAutoLogin()) + { + $cookie=new THttpCookie($this->getUserKey(),''); + $this->getResponse()->getCookies()->add($cookie); + } + } +} + +?> diff --git a/framework/Security/TAuthorizationRule.php b/framework/Security/TAuthorizationRule.php index 6c12d301..4eb32b10 100644 --- a/framework/Security/TAuthorizationRule.php +++ b/framework/Security/TAuthorizationRule.php @@ -1,296 +1,296 @@ -<?php
-/**
- * TAuthorizationRule, TAuthorizationRuleCollection class file
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TAuthorizationRule, TAuthorizationRuleCollection class file + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Security
- */
-/**
- * TAuthorizationRule class
- *
- * TAuthorizationRule represents a single authorization rule.
- * A rule is specified by an action (required), a list of users (optional),
- * a list of roles (optional), a verb (optional), and a list of IP rules (optional).
- * Action can be either 'allow' or 'deny'.
- * Guest (anonymous, unauthenticated) users are represented by question mark '?'.
- * All users (including guest users) are represented by asterisk '*'.
- * Authenticated users are represented by '@'.
- * Users/roles are case-insensitive.
- * Different users/roles are separated by comma ','.
- * Verb can be either 'get' or 'post'. If it is absent, it means both.
- * IP rules are separated by comma ',' and can contain wild card in the rules (e.g. '192.132.23.33, 192.122.*.*')
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Security
- * @since 3.0
- */
-class TAuthorizationRule extends TComponent
-{
- /**
- * @var string action, either 'allow' or 'deny'
- */
- private $_action;
- /**
- * @var array list of user IDs
- */
- private $_users;
- /**
- * @var array list of roles
- */
- private $_roles;
- /**
- * @var string verb, may be empty, 'get', or 'post'.
- */
- private $_verb;
- /**
- * @var string IP patterns
- */
- private $_ipRules;
- /**
- * @var boolean if this rule applies to everyone
- */
- private $_everyone;
- /**
- * @var boolean if this rule applies to guest user
- */
- private $_guest;
- /**
- * @var boolean if this rule applies to authenticated users
- */
- private $_authenticated;
-
- /**
- * Constructor.
- * @param string action, either 'deny' or 'allow'
- * @param string a comma separated user list
- * @param string a comma separated role list
- * @param string verb, can be empty, 'get', or 'post'
- * @param string IP rules (separated by comma, can contain wild card *)
- */
- public function __construct($action,$users,$roles,$verb='',$ipRules='')
- {
- $action=strtolower(trim($action));
- if($action==='allow' || $action==='deny')
- $this->_action=$action;
- else
- throw new TInvalidDataValueException('authorizationrule_action_invalid',$action);
- $this->_users=array();
- $this->_roles=array();
- $this->_ipRules=array();
- $this->_everyone=false;
- $this->_guest=false;
- $this->_authenticated=false;
-
- if(trim($users)==='')
- $users='*';
- foreach(explode(',',$users) as $user)
- {
- if(($user=trim(strtolower($user)))!=='')
- {
- if($user==='*')
- {
- $this->_everyone=true;
- break;
- }
- else if($user==='?')
- $this->_guest=true;
- else if($user==='@')
- $this->_authenticated=true;
- else
- $this->_users[]=$user;
- }
- }
-
- if(trim($roles)==='')
- $roles='*';
- foreach(explode(',',$roles) as $role)
- {
- if(($role=trim(strtolower($role)))!=='')
- $this->_roles[]=$role;
- }
-
- if(($verb=trim(strtolower($verb)))==='')
- $verb='*';
- if($verb==='*' || $verb==='get' || $verb==='post')
- $this->_verb=$verb;
- else
- throw new TInvalidDataValueException('authorizationrule_verb_invalid',$verb);
-
- if(trim($ipRules)==='')
- $ipRules='*';
- foreach(explode(',',$ipRules) as $ipRule)
- {
- if(($ipRule=trim($ipRule))!=='')
- $this->_ipRules[]=$ipRule;
- }
- }
-
- /**
- * @return string action, either 'allow' or 'deny'
- */
- public function getAction()
- {
- return $this->_action;
- }
-
- /**
- * @return array list of user IDs
- */
- public function getUsers()
- {
- return $this->_users;
- }
-
- /**
- * @return array list of roles
- */
- public function getRoles()
- {
- return $this->_roles;
- }
-
- /**
- * @return string verb, may be empty, 'get', or 'post'.
- */
- public function getVerb()
- {
- return $this->_verb;
- }
-
- /**
- * @return array list of IP rules.
- * @since 3.1.1
- */
- public function getIPRules()
- {
- return $this->_ipRules;
- }
-
- /**
- * @return boolean if this rule applies to everyone
- */
- public function getGuestApplied()
- {
- return $this->_guest || $this->_everyone;
- }
-
- /**
- * @return boolean if this rule applies to everyone
- */
- public function getEveryoneApplied()
- {
- return $this->_everyone;
- }
-
- /**
- * @return boolean if this rule applies to authenticated users
- */
- public function getAuthenticatedApplied()
- {
- return $this->_authenticated || $this->_everyone;
- }
-
- /**
- * @param IUser the user object
- * @param string the request verb (GET, PUT)
- * @param string the request IP address
- * @return integer 1 if the user is allowed, -1 if the user is denied, 0 if the rule does not apply to the user
- */
- public function isUserAllowed(IUser $user,$verb,$ip)
- {
- if($this->isVerbMatched($verb) && $this->isIpMatched($ip) && $this->isUserMatched($user) && $this->isRoleMatched($user))
- return ($this->_action==='allow')?1:-1;
- else
- return 0;
- }
-
- private function isIpMatched($ip)
- {
- if(empty($this->_ipRules))
- return 1;
- foreach($this->_ipRules as $rule)
- {
- if($rule==='*' || $rule===$ip || (($pos=strpos($rule,'*'))!==false && strncmp($ip,$rule,$pos)===0))
- return 1;
- }
- return 0;
- }
-
- private function isUserMatched($user)
- {
- return ($this->_everyone || ($this->_guest && $user->getIsGuest()) || ($this->_authenticated && !$user->getIsGuest()) || in_array(strtolower($user->getName()),$this->_users));
- }
-
- private function isRoleMatched($user)
- {
- foreach($this->_roles as $role)
- {
- if($role==='*' || $user->isInRole($role))
- return true;
- }
- return false;
- }
-
- private function isVerbMatched($verb)
- {
- return ($this->_verb==='*' || strcasecmp($verb,$this->_verb)===0);
- }
-}
-
-
-/**
- * TAuthorizationRuleCollection class.
- * TAuthorizationRuleCollection represents a collection of authorization rules {@link TAuthorizationRule}.
- * To check if a user is allowed, call {@link isUserAllowed}.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Security
- * @since 3.0
- */
-class TAuthorizationRuleCollection extends TList
-{
- /**
- * @param IUser the user to be authorized
- * @param string verb, can be empty, 'post' or 'get'.
- * @param string the request IP address
- * @return boolean whether the user is allowed
- */
- public function isUserAllowed($user,$verb,$ip)
- {
- if($user instanceof IUser)
- {
- $verb=strtolower(trim($verb));
- foreach($this as $rule)
- {
- if(($decision=$rule->isUserAllowed($user,$verb,$ip))!==0)
- return ($decision>0);
- }
- return true;
- }
- else
- return false;
- }
-
- /**
- * Inserts an item at the specified position.
- * This overrides the parent implementation by performing additional
- * operations for each newly added TAuthorizationRule object.
- * @param integer the specified position.
- * @param mixed new item
- * @throws TInvalidDataTypeException if the item to be inserted is not a TAuthorizationRule object.
- */
- public function insertAt($index,$item)
- {
- if($item instanceof TAuthorizationRule)
- parent::insertAt($index,$item);
- else
- throw new TInvalidDataTypeException('authorizationrulecollection_authorizationrule_required');
- }
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Security + */ +/** + * TAuthorizationRule class + * + * TAuthorizationRule represents a single authorization rule. + * A rule is specified by an action (required), a list of users (optional), + * a list of roles (optional), a verb (optional), and a list of IP rules (optional). + * Action can be either 'allow' or 'deny'. + * Guest (anonymous, unauthenticated) users are represented by question mark '?'. + * All users (including guest users) are represented by asterisk '*'. + * Authenticated users are represented by '@'. + * Users/roles are case-insensitive. + * Different users/roles are separated by comma ','. + * Verb can be either 'get' or 'post'. If it is absent, it means both. + * IP rules are separated by comma ',' and can contain wild card in the rules (e.g. '192.132.23.33, 192.122.*.*') + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Security + * @since 3.0 + */ +class TAuthorizationRule extends TComponent +{ + /** + * @var string action, either 'allow' or 'deny' + */ + private $_action; + /** + * @var array list of user IDs + */ + private $_users; + /** + * @var array list of roles + */ + private $_roles; + /** + * @var string verb, may be empty, 'get', or 'post'. + */ + private $_verb; + /** + * @var string IP patterns + */ + private $_ipRules; + /** + * @var boolean if this rule applies to everyone + */ + private $_everyone; + /** + * @var boolean if this rule applies to guest user + */ + private $_guest; + /** + * @var boolean if this rule applies to authenticated users + */ + private $_authenticated; + + /** + * Constructor. + * @param string action, either 'deny' or 'allow' + * @param string a comma separated user list + * @param string a comma separated role list + * @param string verb, can be empty, 'get', or 'post' + * @param string IP rules (separated by comma, can contain wild card *) + */ + public function __construct($action,$users,$roles,$verb='',$ipRules='') + { + $action=strtolower(trim($action)); + if($action==='allow' || $action==='deny') + $this->_action=$action; + else + throw new TInvalidDataValueException('authorizationrule_action_invalid',$action); + $this->_users=array(); + $this->_roles=array(); + $this->_ipRules=array(); + $this->_everyone=false; + $this->_guest=false; + $this->_authenticated=false; + + if(trim($users)==='') + $users='*'; + foreach(explode(',',$users) as $user) + { + if(($user=trim(strtolower($user)))!=='') + { + if($user==='*') + { + $this->_everyone=true; + break; + } + else if($user==='?') + $this->_guest=true; + else if($user==='@') + $this->_authenticated=true; + else + $this->_users[]=$user; + } + } + + if(trim($roles)==='') + $roles='*'; + foreach(explode(',',$roles) as $role) + { + if(($role=trim(strtolower($role)))!=='') + $this->_roles[]=$role; + } + + if(($verb=trim(strtolower($verb)))==='') + $verb='*'; + if($verb==='*' || $verb==='get' || $verb==='post') + $this->_verb=$verb; + else + throw new TInvalidDataValueException('authorizationrule_verb_invalid',$verb); + + if(trim($ipRules)==='') + $ipRules='*'; + foreach(explode(',',$ipRules) as $ipRule) + { + if(($ipRule=trim($ipRule))!=='') + $this->_ipRules[]=$ipRule; + } + } + + /** + * @return string action, either 'allow' or 'deny' + */ + public function getAction() + { + return $this->_action; + } + + /** + * @return array list of user IDs + */ + public function getUsers() + { + return $this->_users; + } + + /** + * @return array list of roles + */ + public function getRoles() + { + return $this->_roles; + } + + /** + * @return string verb, may be empty, 'get', or 'post'. + */ + public function getVerb() + { + return $this->_verb; + } + + /** + * @return array list of IP rules. + * @since 3.1.1 + */ + public function getIPRules() + { + return $this->_ipRules; + } + + /** + * @return boolean if this rule applies to everyone + */ + public function getGuestApplied() + { + return $this->_guest || $this->_everyone; + } + + /** + * @return boolean if this rule applies to everyone + */ + public function getEveryoneApplied() + { + return $this->_everyone; + } + + /** + * @return boolean if this rule applies to authenticated users + */ + public function getAuthenticatedApplied() + { + return $this->_authenticated || $this->_everyone; + } + + /** + * @param IUser the user object + * @param string the request verb (GET, PUT) + * @param string the request IP address + * @return integer 1 if the user is allowed, -1 if the user is denied, 0 if the rule does not apply to the user + */ + public function isUserAllowed(IUser $user,$verb,$ip) + { + if($this->isVerbMatched($verb) && $this->isIpMatched($ip) && $this->isUserMatched($user) && $this->isRoleMatched($user)) + return ($this->_action==='allow')?1:-1; + else + return 0; + } + + private function isIpMatched($ip) + { + if(empty($this->_ipRules)) + return 1; + foreach($this->_ipRules as $rule) + { + if($rule==='*' || $rule===$ip || (($pos=strpos($rule,'*'))!==false && strncmp($ip,$rule,$pos)===0)) + return 1; + } + return 0; + } + + private function isUserMatched($user) + { + return ($this->_everyone || ($this->_guest && $user->getIsGuest()) || ($this->_authenticated && !$user->getIsGuest()) || in_array(strtolower($user->getName()),$this->_users)); + } + + private function isRoleMatched($user) + { + foreach($this->_roles as $role) + { + if($role==='*' || $user->isInRole($role)) + return true; + } + return false; + } + + private function isVerbMatched($verb) + { + return ($this->_verb==='*' || strcasecmp($verb,$this->_verb)===0); + } +} + + +/** + * TAuthorizationRuleCollection class. + * TAuthorizationRuleCollection represents a collection of authorization rules {@link TAuthorizationRule}. + * To check if a user is allowed, call {@link isUserAllowed}. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Security + * @since 3.0 + */ +class TAuthorizationRuleCollection extends TList +{ + /** + * @param IUser the user to be authorized + * @param string verb, can be empty, 'post' or 'get'. + * @param string the request IP address + * @return boolean whether the user is allowed + */ + public function isUserAllowed($user,$verb,$ip) + { + if($user instanceof IUser) + { + $verb=strtolower(trim($verb)); + foreach($this as $rule) + { + if(($decision=$rule->isUserAllowed($user,$verb,$ip))!==0) + return ($decision>0); + } + return true; + } + else + return false; + } + + /** + * Inserts an item at the specified position. + * This overrides the parent implementation by performing additional + * operations for each newly added TAuthorizationRule object. + * @param integer the specified position. + * @param mixed new item + * @throws TInvalidDataTypeException if the item to be inserted is not a TAuthorizationRule object. + */ + public function insertAt($index,$item) + { + if($item instanceof TAuthorizationRule) + parent::insertAt($index,$item); + else + throw new TInvalidDataTypeException('authorizationrulecollection_authorizationrule_required'); + } +} + diff --git a/framework/Security/TDbUserManager.php b/framework/Security/TDbUserManager.php index 11dcdadd..8c875148 100644 --- a/framework/Security/TDbUserManager.php +++ b/framework/Security/TDbUserManager.php @@ -1,320 +1,320 @@ -<?php
-/**
- * TDbUserManager class
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TDbUserManager class + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Security
- */
-
-/**
- * Using IUserManager interface
- */
-Prado::using('System.Security.IUserManager');
-Prado::using('System.Data.TDataSourceConfig');
-Prado::using('System.Security.TUser');
-
-/**
- * TDbUserManager class
- *
- * TDbUserManager manages user accounts that are stored in a database.
- * TDbUserManager is mainly designed to be used together with {@link TAuthManager}
- * which manages how users are authenticated and authorized in a Prado application.
- *
- * To use TDbUserManager together with TAuthManager, configure them in
- * the application configuration like following:
- * <code>
- * <module id="db"
- * class="System.Data.TDataSourceConfig" ..../>
- * <module id="users"
- * class="System.Security.TDbUserManager"
- * UserClass="Path.To.MyUserClass"
- * ConnectionID="db" />
- * <module id="auth"
- * class="System.Security.TAuthManager"
- * UserManager="users" LoginPage="Path.To.LoginPage" />
- * </code>
- *
- * In the above, {@link setUserClass UserClass} specifies what class will be used
- * to create user instance. The class must extend from {@link TDbUser}.
- * {@link setConnectionID ConnectionID} refers to the ID of a {@link TDataSourceConfig} module
- * which specifies how to establish database connection to retrieve user information.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Security
- * @since 3.1.0
- */
-class TDbUserManager extends TModule implements IUserManager
-{
- private $_connID='';
- private $_conn;
- private $_guestName='Guest';
- private $_userClass='';
- private $_userFactory;
-
- /**
- * Initializes the module.
- * This method is required by IModule and is invoked by application.
- * @param TXmlElement module configuration
- */
- public function init($config)
- {
- if($this->_userClass==='')
- throw new TConfigurationException('dbusermanager_userclass_required');
- $this->_userFactory=Prado::createComponent($this->_userClass,$this);
- if(!($this->_userFactory instanceof TDbUser))
- throw new TInvalidDataTypeException('dbusermanager_userclass_invalid',$this->_userClass);
- }
-
- /**
- * @return string the user class name in namespace format. Defaults to empty string, meaning not set.
- */
- public function getUserClass()
- {
- return $this->_userClass;
- }
-
- /**
- * @param string the user class name in namespace format. The user class must extend from {@link TDbUser}.
- */
- public function setUserClass($value)
- {
- $this->_userClass=$value;
- }
-
- /**
- * @return string guest name, defaults to 'Guest'
- */
- public function getGuestName()
- {
- return $this->_guestName;
- }
-
- /**
- * @param string name to be used for guest users.
- */
- public function setGuestName($value)
- {
- $this->_guestName=$value;
- }
-
- /**
- * Validates if the username and password are correct.
- * @param string user name
- * @param string password
- * @return boolean true if validation is successful, false otherwise.
- */
- public function validateUser($username,$password)
- {
- return $this->_userFactory->validateUser($username,$password);
- }
-
- /**
- * Returns a user instance given the user name.
- * @param string user name, null if it is a guest.
- * @return TUser the user instance, null if the specified username is not in the user database.
- */
- public function getUser($username=null)
- {
- if($username===null)
- {
- $user=Prado::createComponent($this->_userClass,$this);
- $user->setIsGuest(true);
- return $user;
- }
- else
- return $this->_userFactory->createUser($username);
- }
-
- /**
- * @return string the ID of a TDataSourceConfig module. Defaults to empty string, meaning not set.
- */
- public function getConnectionID()
- {
- return $this->_connID;
- }
-
- /**
- * Sets the ID of a TDataSourceConfig module.
- * The datasource module will be used to establish the DB connection
- * that will be used by the user manager.
- * @param string module ID.
- */
- public function setConnectionID($value)
- {
- $this->_connID=$value;
- }
-
- /**
- * @return TDbConnection the database connection that may be used to retrieve user data.
- */
- public function getDbConnection()
- {
- if($this->_conn===null)
- {
- $this->_conn=$this->createDbConnection($this->_connID);
- $this->_conn->setActive(true);
- }
- return $this->_conn;
- }
-
- /**
- * Creates the DB connection.
- * @param string the module ID for TDataSourceConfig
- * @return TDbConnection the created DB connection
- * @throws TConfigurationException if module ID is invalid or empty
- */
- protected function createDbConnection($connectionID)
- {
- if($connectionID!=='')
- {
- $conn=$this->getApplication()->getModule($connectionID);
- if($conn instanceof TDataSourceConfig)
- return $conn->getDbConnection();
- else
- throw new TConfigurationException('dbusermanager_connectionid_invalid',$connectionID);
- }
- else
- throw new TConfigurationException('dbusermanager_connectionid_required');
- }
-
- /**
- * Returns a user instance according to auth data stored in a cookie.
- * @param THttpCookie the cookie storing user authentication information
- * @return TDbUser the user instance generated based on the cookie auth data, null if the cookie does not have valid auth data.
- * @since 3.1.1
- */
- public function getUserFromCookie($cookie)
- {
- return $this->_userFactory->createUserFromCookie($cookie);
- }
-
- /**
- * Saves user auth data into a cookie.
- * @param THttpCookie the cookie to receive the user auth data.
- * @since 3.1.1
- */
- public function saveUserToCookie($cookie)
- {
- $user=$this->getApplication()->getUser();
- if($user instanceof TDbUser)
- $user->saveUserToCookie($cookie);
- }
-}
-
-
-/**
- * TDbUser class
- *
- * TDbUser is the base user class for using together with {@link TDbUserManager}.
- * Two methods are declared and must be implemented in the descendant classes:
- * - {@link validateUser()}: validates if username and password are correct entries.
- * - {@link createUser()}: creates a new user instance given the username
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Security
- * @since 3.1.0
- */
-abstract class TDbUser extends TUser
-{
- private $_connection;
-
- /**
- * Returns a database connection that may be used to retrieve data from database.
- *
- * @return TDbConnection database connection that may be used to retrieve data from database
- */
- public function getDbConnection()
- {
- if($this->_connection===null)
- {
- $userManager=$this->getManager();
- if($userManager instanceof TDbUserManager)
- {
- $connection=$userManager->getDbConnection();
- if($connection instanceof TDbConnection)
- {
- $connection->setActive(true);
- $this->_connection=$connection;
- }
- }
- if($this->_connection===null)
- throw new TConfigurationException('dbuser_dbconnection_invalid');
- }
- return $this->_connection;
- }
-
- /**
- * Validates if username and password are correct entries.
- * Usually, this is accomplished by checking if the user database
- * contains this (username, password) pair.
- * You may use {@link getDbConnection DbConnection} to deal with database.
- * @param string username (case-sensitive)
- * @param string password
- * @return boolean whether the validation succeeds
- */
- abstract public function validateUser($username,$password);
-
- /**
- * Creates a new user instance given the username.
- * This method usually needs to retrieve necessary user information
- * (e.g. role, name, rank, etc.) from the user database according to
- * the specified username. The newly created user instance should be
- * initialized with these information.
- *
- * If the username is invalid (not found in the user database), null
- * should be returned.
- *
- * You may use {@link getDbConnection DbConnection} to deal with database.
- *
- * @param string username (case-sensitive)
- * @return TDbUser the newly created and initialized user instance
- */
- abstract public function createUser($username);
-
- /**
- * Creates a new user instance given the cookie containing auth data.
- *
- * This method is invoked when {@link TAuthManager::setAllowAutoLogin AllowAutoLogin} is set true.
- * The default implementation simply returns null, meaning no user instance can be created
- * from the given cookie.
- *
- * If you want to support automatic login (remember login), you should override this method.
- * Typically, you obtain the username and a unique token from the cookie's value.
- * You then verify the token is valid and use the username to create a user instance.
- *
- * @param THttpCookie the cookie storing user authentication information
- * @return TDbUser the user instance generated based on the cookie auth data, null if the cookie does not have valid auth data.
- * @see saveUserToCookie
- * @since 3.1.1
- */
- public function createUserFromCookie($cookie)
- {
- return null;
- }
-
- /**
- * Saves necessary auth data into a cookie.
- * This method is invoked when {@link TAuthManager::rememberLogin} is invoked.
- * The default implementation does nothing, meaning auth data is not stored in the cookie
- * (and thus automatic login is not supported.)
- *
- * If you want to support automatic login (remember login), you should override this method.
- * Typically, you generate a unique token according to the current login information
- * and save it together with the username in the cookie's value.
- * You should avoid revealing the password in the generated token.
- *
- * @param THttpCookie the cookie to store the user auth information
- * @see createUserFromCookie
- * @since 3.1.1
- */
- public function saveUserToCookie($cookie)
- {
- }
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Security + */ + +/** + * Using IUserManager interface + */ +Prado::using('System.Security.IUserManager'); +Prado::using('System.Data.TDataSourceConfig'); +Prado::using('System.Security.TUser'); + +/** + * TDbUserManager class + * + * TDbUserManager manages user accounts that are stored in a database. + * TDbUserManager is mainly designed to be used together with {@link TAuthManager} + * which manages how users are authenticated and authorized in a Prado application. + * + * To use TDbUserManager together with TAuthManager, configure them in + * the application configuration like following: + * <code> + * <module id="db" + * class="System.Data.TDataSourceConfig" ..../> + * <module id="users" + * class="System.Security.TDbUserManager" + * UserClass="Path.To.MyUserClass" + * ConnectionID="db" /> + * <module id="auth" + * class="System.Security.TAuthManager" + * UserManager="users" LoginPage="Path.To.LoginPage" /> + * </code> + * + * In the above, {@link setUserClass UserClass} specifies what class will be used + * to create user instance. The class must extend from {@link TDbUser}. + * {@link setConnectionID ConnectionID} refers to the ID of a {@link TDataSourceConfig} module + * which specifies how to establish database connection to retrieve user information. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Security + * @since 3.1.0 + */ +class TDbUserManager extends TModule implements IUserManager +{ + private $_connID=''; + private $_conn; + private $_guestName='Guest'; + private $_userClass=''; + private $_userFactory; + + /** + * Initializes the module. + * This method is required by IModule and is invoked by application. + * @param TXmlElement module configuration + */ + public function init($config) + { + if($this->_userClass==='') + throw new TConfigurationException('dbusermanager_userclass_required'); + $this->_userFactory=Prado::createComponent($this->_userClass,$this); + if(!($this->_userFactory instanceof TDbUser)) + throw new TInvalidDataTypeException('dbusermanager_userclass_invalid',$this->_userClass); + } + + /** + * @return string the user class name in namespace format. Defaults to empty string, meaning not set. + */ + public function getUserClass() + { + return $this->_userClass; + } + + /** + * @param string the user class name in namespace format. The user class must extend from {@link TDbUser}. + */ + public function setUserClass($value) + { + $this->_userClass=$value; + } + + /** + * @return string guest name, defaults to 'Guest' + */ + public function getGuestName() + { + return $this->_guestName; + } + + /** + * @param string name to be used for guest users. + */ + public function setGuestName($value) + { + $this->_guestName=$value; + } + + /** + * Validates if the username and password are correct. + * @param string user name + * @param string password + * @return boolean true if validation is successful, false otherwise. + */ + public function validateUser($username,$password) + { + return $this->_userFactory->validateUser($username,$password); + } + + /** + * Returns a user instance given the user name. + * @param string user name, null if it is a guest. + * @return TUser the user instance, null if the specified username is not in the user database. + */ + public function getUser($username=null) + { + if($username===null) + { + $user=Prado::createComponent($this->_userClass,$this); + $user->setIsGuest(true); + return $user; + } + else + return $this->_userFactory->createUser($username); + } + + /** + * @return string the ID of a TDataSourceConfig module. Defaults to empty string, meaning not set. + */ + public function getConnectionID() + { + return $this->_connID; + } + + /** + * Sets the ID of a TDataSourceConfig module. + * The datasource module will be used to establish the DB connection + * that will be used by the user manager. + * @param string module ID. + */ + public function setConnectionID($value) + { + $this->_connID=$value; + } + + /** + * @return TDbConnection the database connection that may be used to retrieve user data. + */ + public function getDbConnection() + { + if($this->_conn===null) + { + $this->_conn=$this->createDbConnection($this->_connID); + $this->_conn->setActive(true); + } + return $this->_conn; + } + + /** + * Creates the DB connection. + * @param string the module ID for TDataSourceConfig + * @return TDbConnection the created DB connection + * @throws TConfigurationException if module ID is invalid or empty + */ + protected function createDbConnection($connectionID) + { + if($connectionID!=='') + { + $conn=$this->getApplication()->getModule($connectionID); + if($conn instanceof TDataSourceConfig) + return $conn->getDbConnection(); + else + throw new TConfigurationException('dbusermanager_connectionid_invalid',$connectionID); + } + else + throw new TConfigurationException('dbusermanager_connectionid_required'); + } + + /** + * Returns a user instance according to auth data stored in a cookie. + * @param THttpCookie the cookie storing user authentication information + * @return TDbUser the user instance generated based on the cookie auth data, null if the cookie does not have valid auth data. + * @since 3.1.1 + */ + public function getUserFromCookie($cookie) + { + return $this->_userFactory->createUserFromCookie($cookie); + } + + /** + * Saves user auth data into a cookie. + * @param THttpCookie the cookie to receive the user auth data. + * @since 3.1.1 + */ + public function saveUserToCookie($cookie) + { + $user=$this->getApplication()->getUser(); + if($user instanceof TDbUser) + $user->saveUserToCookie($cookie); + } +} + + +/** + * TDbUser class + * + * TDbUser is the base user class for using together with {@link TDbUserManager}. + * Two methods are declared and must be implemented in the descendant classes: + * - {@link validateUser()}: validates if username and password are correct entries. + * - {@link createUser()}: creates a new user instance given the username + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Security + * @since 3.1.0 + */ +abstract class TDbUser extends TUser +{ + private $_connection; + + /** + * Returns a database connection that may be used to retrieve data from database. + * + * @return TDbConnection database connection that may be used to retrieve data from database + */ + public function getDbConnection() + { + if($this->_connection===null) + { + $userManager=$this->getManager(); + if($userManager instanceof TDbUserManager) + { + $connection=$userManager->getDbConnection(); + if($connection instanceof TDbConnection) + { + $connection->setActive(true); + $this->_connection=$connection; + } + } + if($this->_connection===null) + throw new TConfigurationException('dbuser_dbconnection_invalid'); + } + return $this->_connection; + } + + /** + * Validates if username and password are correct entries. + * Usually, this is accomplished by checking if the user database + * contains this (username, password) pair. + * You may use {@link getDbConnection DbConnection} to deal with database. + * @param string username (case-sensitive) + * @param string password + * @return boolean whether the validation succeeds + */ + abstract public function validateUser($username,$password); + + /** + * Creates a new user instance given the username. + * This method usually needs to retrieve necessary user information + * (e.g. role, name, rank, etc.) from the user database according to + * the specified username. The newly created user instance should be + * initialized with these information. + * + * If the username is invalid (not found in the user database), null + * should be returned. + * + * You may use {@link getDbConnection DbConnection} to deal with database. + * + * @param string username (case-sensitive) + * @return TDbUser the newly created and initialized user instance + */ + abstract public function createUser($username); + + /** + * Creates a new user instance given the cookie containing auth data. + * + * This method is invoked when {@link TAuthManager::setAllowAutoLogin AllowAutoLogin} is set true. + * The default implementation simply returns null, meaning no user instance can be created + * from the given cookie. + * + * If you want to support automatic login (remember login), you should override this method. + * Typically, you obtain the username and a unique token from the cookie's value. + * You then verify the token is valid and use the username to create a user instance. + * + * @param THttpCookie the cookie storing user authentication information + * @return TDbUser the user instance generated based on the cookie auth data, null if the cookie does not have valid auth data. + * @see saveUserToCookie + * @since 3.1.1 + */ + public function createUserFromCookie($cookie) + { + return null; + } + + /** + * Saves necessary auth data into a cookie. + * This method is invoked when {@link TAuthManager::rememberLogin} is invoked. + * The default implementation does nothing, meaning auth data is not stored in the cookie + * (and thus automatic login is not supported.) + * + * If you want to support automatic login (remember login), you should override this method. + * Typically, you generate a unique token according to the current login information + * and save it together with the username in the cookie's value. + * You should avoid revealing the password in the generated token. + * + * @param THttpCookie the cookie to store the user auth information + * @see createUserFromCookie + * @since 3.1.1 + */ + public function saveUserToCookie($cookie) + { + } +} + diff --git a/framework/Security/TUser.php b/framework/Security/TUser.php index b282234b..2b367255 100644 --- a/framework/Security/TUser.php +++ b/framework/Security/TUser.php @@ -1,222 +1,222 @@ -<?php
-/**
- * TUser class file.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TUser class file. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Security
- */
-
-/**
- * Using IUserManager interface
- */
-Prado::using('System.Security.IUserManager');
-
-/**
- * TUser class
- *
- * TUser implements basic user functionality for a Prado application.
- * To get the name of the user, use {@link getName Name} property.
- * The property {@link getIsGuest IsGuest} tells if the user a guest/anonymous user.
- * To obtain or test the roles that the user is in, use property
- * {@link getRoles Roles} and call {@link isInRole()}, respectively.
- *
- * TUser is meant to be used together with {@link IUserManager}.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Security
- * @since 3.0
- */
-class TUser extends TComponent implements IUser
-{
- /**
- * @var array persistent state
- */
- private $_state;
- /**
- * @var boolean whether user state is changed
- */
- private $_stateChanged=false;
- /**
- * @var IUserManager user manager
- */
- private $_manager;
-
- /**
- * Constructor.
- * @param IUserManager user manager
- */
- public function __construct(IUserManager $manager)
- {
- $this->_state=array();
- $this->_manager=$manager;
- $this->setName($manager->getGuestName());
- }
-
- /**
- * @return IUserManager user manager
- */
- public function getManager()
- {
- return $this->_manager;
- }
-
- /**
- * @return string username, defaults to empty string.
- */
- public function getName()
- {
- return $this->getState('Name','');
- }
-
- /**
- * @param string username
- */
- public function setName($value)
- {
- $this->setState('Name',$value,'');
- }
-
- /**
- * @return boolean if the user is a guest, defaults to true.
- */
- public function getIsGuest()
- {
- return $this->getState('IsGuest',true);
- }
-
- /**
- * @param boolean if the user is a guest
- */
- public function setIsGuest($value)
- {
- if($isGuest=TPropertyValue::ensureBoolean($value))
- {
- $this->setName($this->_manager->getGuestName());
- $this->setRoles(array());
- }
- $this->setState('IsGuest',$isGuest);
- }
-
- /**
- * @return array list of roles that the user is of
- */
- public function getRoles()
- {
- return $this->getState('Roles',array());
- }
-
- /**
- * @return array|string list of roles that the user is of. If it is a string, roles are assumed by separated by comma
- */
- public function setRoles($value)
- {
- if(is_array($value))
- $this->setState('Roles',$value,array());
- else
- {
- $roles=array();
- foreach(explode(',',$value) as $role)
- {
- if(($role=trim($role))!=='')
- $roles[]=$role;
- }
- $this->setState('Roles',$roles,array());
- }
- }
-
- /**
- * @param string role to be tested. Note, role is case-insensitive.
- * @return boolean whether the user is of this role
- */
- public function isInRole($role)
- {
- foreach($this->getRoles() as $r)
- if(strcasecmp($role,$r)===0)
- return true;
- return false;
- }
-
- /**
- * @return string user data that is serialized and will be stored in session
- */
- public function saveToString()
- {
- return serialize($this->_state);
- }
-
- /**
- * @param string user data that is serialized and restored from session
- * @return IUser the user object
- */
- public function loadFromString($data)
- {
- if(!empty($data))
- $this->_state=unserialize($data);
- if(!is_array($this->_state))
- $this->_state=array();
- return $this;
- }
-
- /**
- * Returns the value of a variable that is stored in user session.
- *
- * This function is designed to be used by TUser descendant classes
- * who want to store additional user information in user session.
- * A variable, if stored in user session using {@link setState} can be
- * retrieved back using this function.
- *
- * @param string variable name
- * @param mixed default value
- * @return mixed the value of the variable. If it doesn't exist, the provided default value will be returned
- * @see setState
- */
- protected function getState($key,$defaultValue=null)
- {
- return isset($this->_state[$key])?$this->_state[$key]:$defaultValue;
- }
-
- /**
- * Stores a variable in user session.
- *
- * This function is designed to be used by TUser descendant classes
- * who want to store additional user information in user session.
- * By storing a variable using this function, the variable may be retrieved
- * back later using {@link getState}. The variable will be persistent
- * across page requests during a user session.
- *
- * @param string variable name
- * @param mixed variable value
- * @param mixed default value. If $value===$defaultValue, the variable will be removed from persistent storage.
- * @see getState
- */
- protected function setState($key,$value,$defaultValue=null)
- {
- if($value===$defaultValue)
- unset($this->_state[$key]);
- else
- $this->_state[$key]=$value;
- $this->_stateChanged=true;
- }
-
- /**
- * @return boolean whether user session state is changed (i.e., setState() is called)
- */
- public function getStateChanged()
- {
- return $this->_stateChanged;
- }
-
- /**
- * @param boolean whether user session state is changed
- */
- public function setStateChanged($value)
- {
- $this->_stateChanged=TPropertyValue::ensureBoolean($value);
- }
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Security + */ + +/** + * Using IUserManager interface + */ +Prado::using('System.Security.IUserManager'); + +/** + * TUser class + * + * TUser implements basic user functionality for a Prado application. + * To get the name of the user, use {@link getName Name} property. + * The property {@link getIsGuest IsGuest} tells if the user a guest/anonymous user. + * To obtain or test the roles that the user is in, use property + * {@link getRoles Roles} and call {@link isInRole()}, respectively. + * + * TUser is meant to be used together with {@link IUserManager}. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Security + * @since 3.0 + */ +class TUser extends TComponent implements IUser +{ + /** + * @var array persistent state + */ + private $_state; + /** + * @var boolean whether user state is changed + */ + private $_stateChanged=false; + /** + * @var IUserManager user manager + */ + private $_manager; + + /** + * Constructor. + * @param IUserManager user manager + */ + public function __construct(IUserManager $manager) + { + $this->_state=array(); + $this->_manager=$manager; + $this->setName($manager->getGuestName()); + } + + /** + * @return IUserManager user manager + */ + public function getManager() + { + return $this->_manager; + } + + /** + * @return string username, defaults to empty string. + */ + public function getName() + { + return $this->getState('Name',''); + } + + /** + * @param string username + */ + public function setName($value) + { + $this->setState('Name',$value,''); + } + + /** + * @return boolean if the user is a guest, defaults to true. + */ + public function getIsGuest() + { + return $this->getState('IsGuest',true); + } + + /** + * @param boolean if the user is a guest + */ + public function setIsGuest($value) + { + if($isGuest=TPropertyValue::ensureBoolean($value)) + { + $this->setName($this->_manager->getGuestName()); + $this->setRoles(array()); + } + $this->setState('IsGuest',$isGuest); + } + + /** + * @return array list of roles that the user is of + */ + public function getRoles() + { + return $this->getState('Roles',array()); + } + + /** + * @return array|string list of roles that the user is of. If it is a string, roles are assumed by separated by comma + */ + public function setRoles($value) + { + if(is_array($value)) + $this->setState('Roles',$value,array()); + else + { + $roles=array(); + foreach(explode(',',$value) as $role) + { + if(($role=trim($role))!=='') + $roles[]=$role; + } + $this->setState('Roles',$roles,array()); + } + } + + /** + * @param string role to be tested. Note, role is case-insensitive. + * @return boolean whether the user is of this role + */ + public function isInRole($role) + { + foreach($this->getRoles() as $r) + if(strcasecmp($role,$r)===0) + return true; + return false; + } + + /** + * @return string user data that is serialized and will be stored in session + */ + public function saveToString() + { + return serialize($this->_state); + } + + /** + * @param string user data that is serialized and restored from session + * @return IUser the user object + */ + public function loadFromString($data) + { + if(!empty($data)) + $this->_state=unserialize($data); + if(!is_array($this->_state)) + $this->_state=array(); + return $this; + } + + /** + * Returns the value of a variable that is stored in user session. + * + * This function is designed to be used by TUser descendant classes + * who want to store additional user information in user session. + * A variable, if stored in user session using {@link setState} can be + * retrieved back using this function. + * + * @param string variable name + * @param mixed default value + * @return mixed the value of the variable. If it doesn't exist, the provided default value will be returned + * @see setState + */ + protected function getState($key,$defaultValue=null) + { + return isset($this->_state[$key])?$this->_state[$key]:$defaultValue; + } + + /** + * Stores a variable in user session. + * + * This function is designed to be used by TUser descendant classes + * who want to store additional user information in user session. + * By storing a variable using this function, the variable may be retrieved + * back later using {@link getState}. The variable will be persistent + * across page requests during a user session. + * + * @param string variable name + * @param mixed variable value + * @param mixed default value. If $value===$defaultValue, the variable will be removed from persistent storage. + * @see getState + */ + protected function setState($key,$value,$defaultValue=null) + { + if($value===$defaultValue) + unset($this->_state[$key]); + else + $this->_state[$key]=$value; + $this->_stateChanged=true; + } + + /** + * @return boolean whether user session state is changed (i.e., setState() is called) + */ + public function getStateChanged() + { + return $this->_stateChanged; + } + + /** + * @param boolean whether user session state is changed + */ + public function setStateChanged($value) + { + $this->_stateChanged=TPropertyValue::ensureBoolean($value); + } +} + diff --git a/framework/Security/TUserManager.php b/framework/Security/TUserManager.php index 418da79c..c66ce8ad 100644 --- a/framework/Security/TUserManager.php +++ b/framework/Security/TUserManager.php @@ -1,402 +1,402 @@ -<?php
-/**
- * TUserManager class
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
+<?php +/** + * TUserManager class + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Security
- */
-
-/**
- * Using TUser class
- */
-Prado::using('System.Security.TUser');
-
-/**
- * TUserManager class
- *
- * TUserManager manages a static list of users {@link TUser}.
- * The user information is specified via module configuration using the following XML syntax,
- * <code>
- * <module id="users" class="System.Security.TUserManager" PasswordMode="Clear">
- * <user name="Joe" password="demo" />
- * <user name="John" password="demo" />
- * <role name="Administrator" users="John" />
- * <role name="Writer" users="Joe,John" />
- * </module>
- * </code>
- *
- * PHP configuration style:
- * <code>
- * array(
- * 'users' => array(
- * 'class' => 'System.Security.TUserManager',
- * 'properties' => array(
- * 'PasswordMode' => 'Clear',
- * ),
- * 'users' => array(
- * array('name'=>'Joe','password'=>'demo'),
- * array('name'=>'John','password'=>'demo'),
- * ),
- * 'roles' => array(
- * array('name'=>'Administrator','users'=>'John'),
- * array('name'=>'Writer','users'=>'Joe,John'),
- * ),
- * ),
- * )
- * </code>
- *
- * In addition, user information can also be loaded from an external file
- * specified by {@link setUserFile UserFile} property. Note, the property
- * only accepts a file path in namespace format. The user file format is
- * similar to the above sample.
- *
- * The user passwords may be specified as clear text, SH1 or MD5 hashed by setting
- * {@link setPasswordMode PasswordMode} as <b>Clear</b>, <b>SHA1</b> or <b>MD5</b>.
- * The default name for a guest user is <b>Guest</b>. It may be changed
- * by setting {@link setGuestName GuestName} property.
- *
- * TUserManager may be used together with {@link TAuthManager} which manages
- * how users are authenticated and authorized in a Prado application.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @author Carl Mathisen <carl@kamikazemedia.no>
- * @version $Id$
- * @package System.Security
- * @since 3.0
- */
-class TUserManager extends TModule implements IUserManager
-{
- /**
- * extension name to the user file
- */
- const USER_FILE_EXT='.xml';
-
- /**
- * @var array list of users managed by this module
- */
- private $_users=array();
- /**
- * @var array list of roles managed by this module
- */
- private $_roles=array();
- /**
- * @var string guest name
- */
- private $_guestName='Guest';
- /**
- * @var TUserManagerPasswordMode password mode
- */
- private $_passwordMode=TUserManagerPasswordMode::MD5;
- /**
- * @var boolean whether the module has been initialized
- */
- private $_initialized=false;
- /**
- * @var string user/role information file
- */
- private $_userFile=null;
-
- /**
- * Initializes the module.
- * This method is required by IModule and is invoked by application.
- * It loads user/role information from the module configuration.
- * @param mixed module configuration
- */
- public function init($config)
- {
- $this->loadUserData($config);
- if($this->_userFile!==null)
- {
- if($this->getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP)
- {
- $userFile = include $this->_userFile;
- $this->loadUserDataFromPhp($userFile);
- }
- else
- {
- $dom=new TXmlDocument;
- $dom->loadFromFile($this->_userFile);
- $this->loadUserDataFromXml($dom);
- }
- }
- $this->_initialized=true;
- }
-
- /*
- * Loads user/role information
- * @param mixed the variable containing the user information
- */
- private function loadUserData($config)
- {
- if($this->getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP)
- $this->loadUserDataFromPhp($config);
- else
- $this->loadUserDataFromXml($config);
- }
-
- /**
- * Loads user/role information from an php array.
- * @param array the array containing the user information
- */
- private function loadUserDataFromPhp($config)
- {
- if(isset($config['users']) && is_array($config['users']))
- {
- foreach($config['users'] as $user)
- {
- $name = trim(strtolower(isset($user['name'])?$user['name']:''));
- $password = isset($user['password'])?$user['password']:'';
- $this->_users[$name] = $password;
- $roles = isset($user['roles'])?$user['roles']:'';
- if($roles!=='')
- {
- foreach(explode(',',$roles) as $role)
- {
- if(($role=trim($role))!=='')
- $this->_roles[$name][]=$role;
- }
- }
- }
- }
- if(isset($config['roles']) && is_array($config['roles']))
- {
- foreach($config['roles'] as $role)
- {
- $name = isset($role['name'])?$role['name']:'';
- $users = isset($role['users'])?$role['users']:'';
- foreach(explode(',',$users) as $user)
- {
- if(($user=trim($user))!=='')
- $this->_roles[strtolower($user)][]=$name;
- }
- }
- }
- }
-
- /**
- * Loads user/role information from an XML node.
- * @param TXmlElement the XML node containing the user information
- */
- private function loadUserDataFromXml($xmlNode)
- {
- foreach($xmlNode->getElementsByTagName('user') as $node)
- {
- $name=trim(strtolower($node->getAttribute('name')));
- $this->_users[$name]=$node->getAttribute('password');
- if(($roles=trim($node->getAttribute('roles')))!=='')
- {
- foreach(explode(',',$roles) as $role)
- {
- if(($role=trim($role))!=='')
- $this->_roles[$name][]=$role;
- }
- }
- }
- foreach($xmlNode->getElementsByTagName('role') as $node)
- {
- foreach(explode(',',$node->getAttribute('users')) as $user)
- {
- if(($user=trim($user))!=='')
- $this->_roles[strtolower($user)][]=$node->getAttribute('name');
- }
- }
- }
-
- /**
- * Returns an array of all users.
- * Each array element represents a single user.
- * The array key is the username in lower case, and the array value is the
- * corresponding user password.
- * @return array list of users
- */
- public function getUsers()
- {
- return $this->_users;
- }
-
- /**
- * Returns an array of user role information.
- * Each array element represents the roles for a single user.
- * The array key is the username in lower case, and the array value is
- * the roles (represented as an array) that the user is in.
- * @return array list of user role information
- */
- public function getRoles()
- {
- return $this->_roles;
- }
-
- /**
- * @return string the full path to the file storing user/role information
- */
- public function getUserFile()
- {
- return $this->_userFile;
- }
-
- /**
- * @param string user/role data file path (in namespace form). The file format is XML
- * whose content is similar to that user/role block in application configuration.
- * @throws TInvalidOperationException if the module is already initialized
- * @throws TConfigurationException if the file is not in proper namespace format
- */
- public function setUserFile($value)
- {
- if($this->_initialized)
- throw new TInvalidOperationException('usermanager_userfile_unchangeable');
- else if(($this->_userFile=Prado::getPathOfNamespace($value,self::USER_FILE_EXT))===null || !is_file($this->_userFile))
- throw new TConfigurationException('usermanager_userfile_invalid',$value);
- }
-
- /**
- * @return string guest name, defaults to 'Guest'
- */
- public function getGuestName()
- {
- return $this->_guestName;
- }
-
- /**
- * @param string name to be used for guest users.
- */
- public function setGuestName($value)
- {
- $this->_guestName=$value;
- }
-
- /**
- * @return TUserManagerPasswordMode how password is stored, clear text, or MD5 or SHA1 hashed. Default to TUserManagerPasswordMode::MD5.
- */
- public function getPasswordMode()
- {
- return $this->_passwordMode;
- }
-
- /**
- * @param TUserManagerPasswordMode how password is stored, clear text, or MD5 or SHA1 hashed.
- */
- public function setPasswordMode($value)
- {
- $this->_passwordMode=TPropertyValue::ensureEnum($value,'TUserManagerPasswordMode');
- }
-
- /**
- * Validates if the username and password are correct.
- * @param string user name
- * @param string password
- * @return boolean true if validation is successful, false otherwise.
- */
- public function validateUser($username,$password)
- {
- if($this->_passwordMode===TUserManagerPasswordMode::MD5)
- $password=md5($password);
- else if($this->_passwordMode===TUserManagerPasswordMode::SHA1)
- $password=sha1($password);
- $username=strtolower($username);
- return (isset($this->_users[$username]) && $this->_users[$username]===$password);
- }
-
- /**
- * Returns a user instance given the user name.
- * @param string user name, null if it is a guest.
- * @return TUser the user instance, null if the specified username is not in the user database.
- */
- public function getUser($username=null)
- {
- if($username===null)
- {
- $user=new TUser($this);
- $user->setIsGuest(true);
- return $user;
- }
- else
- {
- $username=strtolower($username);
- if(isset($this->_users[$username]))
- {
- $user=new TUser($this);
- $user->setName($username);
- $user->setIsGuest(false);
- if(isset($this->_roles[$username]))
- $user->setRoles($this->_roles[$username]);
- return $user;
- }
- else
- return null;
- }
- }
-
- /**
- * Returns a user instance according to auth data stored in a cookie.
- * @param THttpCookie the cookie storing user authentication information
- * @return TUser the user instance generated based on the cookie auth data, null if the cookie does not have valid auth data.
- * @since 3.1.1
- */
- public function getUserFromCookie($cookie)
- {
- if(($data=$cookie->getValue())!=='')
- {
- $data=unserialize($data);
- if(is_array($data) && count($data)===2)
- {
- list($username,$token)=$data;
- if(isset($this->_users[$username]) && $token===md5($username.$this->_users[$username]))
- return $this->getUser($username);
- }
- }
- return null;
- }
-
- /**
- * Saves user auth data into a cookie.
- * @param THttpCookie the cookie to receive the user auth data.
- * @since 3.1.1
- */
- public function saveUserToCookie($cookie)
- {
- $user=$this->getApplication()->getUser();
- $username=strtolower($user->getName());
- if(isset($this->_users[$username]))
- {
- $data=array($username,md5($username.$this->_users[$username]));
- $cookie->setValue(serialize($data));
- }
- }
-
- /**
- * Sets a user as a guest.
- * User name is changed as guest name, and roles are emptied.
- * @param TUser the user to be changed to a guest.
- */
- public function switchToGuest($user)
- {
- $user->setIsGuest(true);
- }
-}
-
-/**
- * TUserManagerPasswordMode class.
- * TUserManagerPasswordMode defines the enumerable type for the possible modes
- * that user passwords can be specified for a {@link TUserManager}.
- *
- * The following enumerable values are defined:
- * - Clear: the password is in plain text
- * - MD5: the password is recorded as the MD5 hash value of the original password
- * - SHA1: the password is recorded as the SHA1 hash value of the original password
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Security
- * @since 3.0.4
- */
-class TUserManagerPasswordMode extends TEnumerable
-{
- const Clear='Clear';
- const MD5='MD5';
- const SHA1='SHA1';
-}
-
+ * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Security + */ + +/** + * Using TUser class + */ +Prado::using('System.Security.TUser'); + +/** + * TUserManager class + * + * TUserManager manages a static list of users {@link TUser}. + * The user information is specified via module configuration using the following XML syntax, + * <code> + * <module id="users" class="System.Security.TUserManager" PasswordMode="Clear"> + * <user name="Joe" password="demo" /> + * <user name="John" password="demo" /> + * <role name="Administrator" users="John" /> + * <role name="Writer" users="Joe,John" /> + * </module> + * </code> + * + * PHP configuration style: + * <code> + * array( + * 'users' => array( + * 'class' => 'System.Security.TUserManager', + * 'properties' => array( + * 'PasswordMode' => 'Clear', + * ), + * 'users' => array( + * array('name'=>'Joe','password'=>'demo'), + * array('name'=>'John','password'=>'demo'), + * ), + * 'roles' => array( + * array('name'=>'Administrator','users'=>'John'), + * array('name'=>'Writer','users'=>'Joe,John'), + * ), + * ), + * ) + * </code> + * + * In addition, user information can also be loaded from an external file + * specified by {@link setUserFile UserFile} property. Note, the property + * only accepts a file path in namespace format. The user file format is + * similar to the above sample. + * + * The user passwords may be specified as clear text, SH1 or MD5 hashed by setting + * {@link setPasswordMode PasswordMode} as <b>Clear</b>, <b>SHA1</b> or <b>MD5</b>. + * The default name for a guest user is <b>Guest</b>. It may be changed + * by setting {@link setGuestName GuestName} property. + * + * TUserManager may be used together with {@link TAuthManager} which manages + * how users are authenticated and authorized in a Prado application. + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @author Carl Mathisen <carl@kamikazemedia.no> + * @version $Id$ + * @package System.Security + * @since 3.0 + */ +class TUserManager extends TModule implements IUserManager +{ + /** + * extension name to the user file + */ + const USER_FILE_EXT='.xml'; + + /** + * @var array list of users managed by this module + */ + private $_users=array(); + /** + * @var array list of roles managed by this module + */ + private $_roles=array(); + /** + * @var string guest name + */ + private $_guestName='Guest'; + /** + * @var TUserManagerPasswordMode password mode + */ + private $_passwordMode=TUserManagerPasswordMode::MD5; + /** + * @var boolean whether the module has been initialized + */ + private $_initialized=false; + /** + * @var string user/role information file + */ + private $_userFile=null; + + /** + * Initializes the module. + * This method is required by IModule and is invoked by application. + * It loads user/role information from the module configuration. + * @param mixed module configuration + */ + public function init($config) + { + $this->loadUserData($config); + if($this->_userFile!==null) + { + if($this->getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP) + { + $userFile = include $this->_userFile; + $this->loadUserDataFromPhp($userFile); + } + else + { + $dom=new TXmlDocument; + $dom->loadFromFile($this->_userFile); + $this->loadUserDataFromXml($dom); + } + } + $this->_initialized=true; + } + + /* + * Loads user/role information + * @param mixed the variable containing the user information + */ + private function loadUserData($config) + { + if($this->getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP) + $this->loadUserDataFromPhp($config); + else + $this->loadUserDataFromXml($config); + } + + /** + * Loads user/role information from an php array. + * @param array the array containing the user information + */ + private function loadUserDataFromPhp($config) + { + if(isset($config['users']) && is_array($config['users'])) + { + foreach($config['users'] as $user) + { + $name = trim(strtolower(isset($user['name'])?$user['name']:'')); + $password = isset($user['password'])?$user['password']:''; + $this->_users[$name] = $password; + $roles = isset($user['roles'])?$user['roles']:''; + if($roles!=='') + { + foreach(explode(',',$roles) as $role) + { + if(($role=trim($role))!=='') + $this->_roles[$name][]=$role; + } + } + } + } + if(isset($config['roles']) && is_array($config['roles'])) + { + foreach($config['roles'] as $role) + { + $name = isset($role['name'])?$role['name']:''; + $users = isset($role['users'])?$role['users']:''; + foreach(explode(',',$users) as $user) + { + if(($user=trim($user))!=='') + $this->_roles[strtolower($user)][]=$name; + } + } + } + } + + /** + * Loads user/role information from an XML node. + * @param TXmlElement the XML node containing the user information + */ + private function loadUserDataFromXml($xmlNode) + { + foreach($xmlNode->getElementsByTagName('user') as $node) + { + $name=trim(strtolower($node->getAttribute('name'))); + $this->_users[$name]=$node->getAttribute('password'); + if(($roles=trim($node->getAttribute('roles')))!=='') + { + foreach(explode(',',$roles) as $role) + { + if(($role=trim($role))!=='') + $this->_roles[$name][]=$role; + } + } + } + foreach($xmlNode->getElementsByTagName('role') as $node) + { + foreach(explode(',',$node->getAttribute('users')) as $user) + { + if(($user=trim($user))!=='') + $this->_roles[strtolower($user)][]=$node->getAttribute('name'); + } + } + } + + /** + * Returns an array of all users. + * Each array element represents a single user. + * The array key is the username in lower case, and the array value is the + * corresponding user password. + * @return array list of users + */ + public function getUsers() + { + return $this->_users; + } + + /** + * Returns an array of user role information. + * Each array element represents the roles for a single user. + * The array key is the username in lower case, and the array value is + * the roles (represented as an array) that the user is in. + * @return array list of user role information + */ + public function getRoles() + { + return $this->_roles; + } + + /** + * @return string the full path to the file storing user/role information + */ + public function getUserFile() + { + return $this->_userFile; + } + + /** + * @param string user/role data file path (in namespace form). The file format is XML + * whose content is similar to that user/role block in application configuration. + * @throws TInvalidOperationException if the module is already initialized + * @throws TConfigurationException if the file is not in proper namespace format + */ + public function setUserFile($value) + { + if($this->_initialized) + throw new TInvalidOperationException('usermanager_userfile_unchangeable'); + else if(($this->_userFile=Prado::getPathOfNamespace($value,self::USER_FILE_EXT))===null || !is_file($this->_userFile)) + throw new TConfigurationException('usermanager_userfile_invalid',$value); + } + + /** + * @return string guest name, defaults to 'Guest' + */ + public function getGuestName() + { + return $this->_guestName; + } + + /** + * @param string name to be used for guest users. + */ + public function setGuestName($value) + { + $this->_guestName=$value; + } + + /** + * @return TUserManagerPasswordMode how password is stored, clear text, or MD5 or SHA1 hashed. Default to TUserManagerPasswordMode::MD5. + */ + public function getPasswordMode() + { + return $this->_passwordMode; + } + + /** + * @param TUserManagerPasswordMode how password is stored, clear text, or MD5 or SHA1 hashed. + */ + public function setPasswordMode($value) + { + $this->_passwordMode=TPropertyValue::ensureEnum($value,'TUserManagerPasswordMode'); + } + + /** + * Validates if the username and password are correct. + * @param string user name + * @param string password + * @return boolean true if validation is successful, false otherwise. + */ + public function validateUser($username,$password) + { + if($this->_passwordMode===TUserManagerPasswordMode::MD5) + $password=md5($password); + else if($this->_passwordMode===TUserManagerPasswordMode::SHA1) + $password=sha1($password); + $username=strtolower($username); + return (isset($this->_users[$username]) && $this->_users[$username]===$password); + } + + /** + * Returns a user instance given the user name. + * @param string user name, null if it is a guest. + * @return TUser the user instance, null if the specified username is not in the user database. + */ + public function getUser($username=null) + { + if($username===null) + { + $user=new TUser($this); + $user->setIsGuest(true); + return $user; + } + else + { + $username=strtolower($username); + if(isset($this->_users[$username])) + { + $user=new TUser($this); + $user->setName($username); + $user->setIsGuest(false); + if(isset($this->_roles[$username])) + $user->setRoles($this->_roles[$username]); + return $user; + } + else + return null; + } + } + + /** + * Returns a user instance according to auth data stored in a cookie. + * @param THttpCookie the cookie storing user authentication information + * @return TUser the user instance generated based on the cookie auth data, null if the cookie does not have valid auth data. + * @since 3.1.1 + */ + public function getUserFromCookie($cookie) + { + if(($data=$cookie->getValue())!=='') + { + $data=unserialize($data); + if(is_array($data) && count($data)===2) + { + list($username,$token)=$data; + if(isset($this->_users[$username]) && $token===md5($username.$this->_users[$username])) + return $this->getUser($username); + } + } + return null; + } + + /** + * Saves user auth data into a cookie. + * @param THttpCookie the cookie to receive the user auth data. + * @since 3.1.1 + */ + public function saveUserToCookie($cookie) + { + $user=$this->getApplication()->getUser(); + $username=strtolower($user->getName()); + if(isset($this->_users[$username])) + { + $data=array($username,md5($username.$this->_users[$username])); + $cookie->setValue(serialize($data)); + } + } + + /** + * Sets a user as a guest. + * User name is changed as guest name, and roles are emptied. + * @param TUser the user to be changed to a guest. + */ + public function switchToGuest($user) + { + $user->setIsGuest(true); + } +} + +/** + * TUserManagerPasswordMode class. + * TUserManagerPasswordMode defines the enumerable type for the possible modes + * that user passwords can be specified for a {@link TUserManager}. + * + * The following enumerable values are defined: + * - Clear: the password is in plain text + * - MD5: the password is recorded as the MD5 hash value of the original password + * - SHA1: the password is recorded as the SHA1 hash value of the original password + * + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id$ + * @package System.Security + * @since 3.0.4 + */ +class TUserManagerPasswordMode extends TEnumerable +{ + const Clear='Clear'; + const MD5='MD5'; + const SHA1='SHA1'; +} + |