summaryrefslogtreecommitdiff
path: root/framework
diff options
context:
space:
mode:
Diffstat (limited to 'framework')
-rw-r--r--framework/Security/IUserManager.php13
-rw-r--r--framework/Security/TAuthManager.php79
-rw-r--r--framework/Security/TDbUserManager.php66
-rw-r--r--framework/Security/TUserManager.php37
-rw-r--r--framework/TApplication.php4
-rw-r--r--framework/Web/THttpRequest.php2
6 files changed, 191 insertions, 10 deletions
diff --git a/framework/Security/IUserManager.php b/framework/Security/IUserManager.php
index 649c41b6..d90450a9 100644
--- a/framework/Security/IUserManager.php
+++ b/framework/Security/IUserManager.php
@@ -35,6 +35,19 @@ interface IUserManager
*/
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
diff --git a/framework/Security/TAuthManager.php b/framework/Security/TAuthManager.php
index fcbb64d2..7a6b96a1 100644
--- a/framework/Security/TAuthManager.php
+++ b/framework/Security/TAuthManager.php
@@ -60,6 +60,14 @@ class TAuthManager extends TModule
* @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;
/**
* Initializes this module.
@@ -216,6 +224,24 @@ class TAuthManager extends TModule
}
/**
+ * @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);
+ }
+
+ /**
* 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.
@@ -227,11 +253,27 @@ class TAuthManager extends TModule
{
$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->generateUserSessionKey());
+ $sessionInfo=$session->itemAt($this->getUserKey());
$user=$this->_userManager->getUser(null)->loadFromString($sessionInfo);
+
+ // try authenticating through cookie if possible
+ if($this->getAllowAutoLogin() && $user->getIsGuest())
+ {
+ $cookie=$this->getRequest()->getCookies()->itemAt($this->getUserKey());
+ if($cookie instanceof THttpCookie)
+ {
+ if(($user2=$this->_userManager->getUserFromCookie($cookie))!==null)
+ {
+ $user=$user2;
+ $this->updateSessionUser($user);
+ }
+ }
+ }
+
$application->setUser($user);
// event handler gets a chance to do further auth work
@@ -259,9 +301,21 @@ class TAuthManager extends TModule
}
/**
+ * @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 generateUserSessionKey()
+ protected function generateUserKey()
{
return md5($this->getApplication()->getUniqueID().'prado:user');
}
@@ -278,7 +332,7 @@ class TAuthManager extends TModule
if(($session=$this->getSession())===null)
throw new TConfigurationException('authmanager_session_required');
else
- $session->add($this->generateUserSessionKey(),$user->saveToString());
+ $session->add($this->getUserKey(),$user->saveToString());
}
}
@@ -288,15 +342,24 @@ class TAuthManager extends TModule
* 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)
+ public function login($username,$password,$expire=0)
{
if($this->_userManager->validateUser($username,$password))
{
$user=$this->_userManager->getUser($username);
$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
@@ -312,10 +375,12 @@ class TAuthManager extends TModule
{
if(($session=$this->getSession())===null)
throw new TConfigurationException('authmanager_session_required');
- else
+ $this->getApplication()->getUser()->setIsGuest(true);
+ $session->destroy();
+ if($this->getAllowAutoLogin())
{
- $this->getApplication()->getUser()->setIsGuest(true);
- $session->destroy();
+ $cookie=new THttpCookie($this->getUserKey(),'');
+ $this->getResponse()->getCookies()->add($cookie);
}
}
}
diff --git a/framework/Security/TDbUserManager.php b/framework/Security/TDbUserManager.php
index a2f30642..35cf4fd7 100644
--- a/framework/Security/TDbUserManager.php
+++ b/framework/Security/TDbUserManager.php
@@ -155,7 +155,10 @@ class TDbUserManager extends TModule implements IUserManager
public function getDbConnection()
{
if($this->_conn===null)
+ {
$this->_conn=$this->createDbConnection($this->_connID);
+ $this->_conn->setActive(true);
+ }
return $this->_conn;
}
@@ -178,6 +181,29 @@ class TDbUserManager extends TModule implements IUserManager
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);
+ }
}
@@ -250,6 +276,46 @@ abstract class TDbUser extends TUser
* @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)
+ {
+ }
}
?> \ No newline at end of file
diff --git a/framework/Security/TUserManager.php b/framework/Security/TUserManager.php
index 28651de8..f6aee767 100644
--- a/framework/Security/TUserManager.php
+++ b/framework/Security/TUserManager.php
@@ -251,6 +251,43 @@ class TUserManager extends TModule implements IUserManager
}
/**
+ * 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.
diff --git a/framework/TApplication.php b/framework/TApplication.php
index 3aa2cec1..a0239072 100644
--- a/framework/TApplication.php
+++ b/framework/TApplication.php
@@ -150,12 +150,12 @@ class TApplication extends TComponent
*/
private static $_steps=array(
'onBeginRequest',
+ 'onLoadState',
+ 'onLoadStateComplete',
'onAuthentication',
'onAuthenticationComplete',
'onAuthorization',
'onAuthorizationComplete',
- 'onLoadState',
- 'onLoadStateComplete',
'onPreRunService',
'runService',
'onSaveState',
diff --git a/framework/Web/THttpRequest.php b/framework/Web/THttpRequest.php
index a9e5fe68..ca7780cd 100644
--- a/framework/Web/THttpRequest.php
+++ b/framework/Web/THttpRequest.php
@@ -911,7 +911,7 @@ class THttpCookie extends TComponent
/**
* @var string value of the cookie
*/
- private $_value=0;
+ private $_value='';
/**
* @var integer expire of the cookie
*/