summaryrefslogtreecommitdiff
path: root/framework/Security
diff options
context:
space:
mode:
authorxue <>2005-11-10 12:47:19 +0000
committerxue <>2005-11-10 12:47:19 +0000
commit55c4ac1bfe565f1ca7f537fdd8b7a201be28e581 (patch)
treea0599d5e36fdbb3f1e169ae56bab7d529597e3eb /framework/Security
Initial import of prado framework
Diffstat (limited to 'framework/Security')
-rw-r--r--framework/Security/TAuthManager.php205
-rw-r--r--framework/Security/TAuthorizationRule.php213
-rw-r--r--framework/Security/TMembershipManager.php109
-rw-r--r--framework/Security/TStaticMembershipProvider.php324
-rw-r--r--framework/Security/TUserManager.php192
5 files changed, 1043 insertions, 0 deletions
diff --git a/framework/Security/TAuthManager.php b/framework/Security/TAuthManager.php
new file mode 100644
index 00000000..c12ee245
--- /dev/null
+++ b/framework/Security/TAuthManager.php
@@ -0,0 +1,205 @@
+<?php
+
+class TAuthManager extends TComponent implements IModule
+{
+ const RETURN_URL_VAR='ReturnUrl';
+ /**
+ * @var TAuthorizationRuleCollection list of authorization rules
+ */
+ private $_authRules=null;
+ private $_guest='Guest';
+ private $_initialized=false;
+ private $_application;
+ private $_users=null;
+ private $_loginPage=null;
+ private $_skipAuthorization=false;
+
+ /**
+ * @return string id of this module
+ */
+ public function getID()
+ {
+ return $this->_id;
+ }
+
+ /**
+ * @param string id of this module
+ */
+ public function setID($value)
+ {
+ $this->_id=$value;
+ }
+
+ /**
+ * Initializes this module.
+ * This method is required by the IModule interface.
+ * @param IApplication Prado application, can be null
+ * @param TXmlElement configuration for this module, can be null
+ */
+ public function init($application,$config)
+ {
+ $this->_application=$application;
+ $application->attachEventHandler('Authentication',array($this,'doAuthentication'));
+ $application->attachEventHandler('EndRequest',array($this,'leave'));
+ $application->attachEventHandler('Authorization',array($this,'doAuthorization'));
+ $this->_initialized=true;
+ }
+
+ public function getGuestName()
+ {
+ return $this->_guest;
+ }
+
+ public function setGuestName($value)
+ {
+ $this->_guest=$value;
+ }
+
+ public function getUserManager()
+ {
+ if($this->_users instanceof TUserManager)
+ return $this->_users;
+ else
+ {
+ if(($users=$this->_application->getModule($this->_users))===null)
+ throw new TConfigurationException('authenticator_usermanager_inexistent',$this->_users);
+ if(!($users instanceof TUserManager))
+ throw new TConfigurationException('authenticator_usermanager_invalid',$this->_users);
+ $this->_users=$users;
+ return $users;
+ }
+ }
+
+ public function setUserManager($provider)
+ {
+ $this->_users=$provider;
+ }
+
+ public function getLoginPage()
+ {
+ return $this->_loginPage;
+ }
+
+ public function setLoginPage($pagePath)
+ {
+ $this->_loginPage=$pagePath;
+ }
+
+ public function doAuthentication($sender,$param)
+ {
+ $this->onAuthenticate($param);
+
+ $service=$this->_application->getService();
+ if(($service instanceof TPageService) && $service->isRequestingPage($this->getLoginPage()))
+ $this->_skipAuthorization=true;
+ }
+
+ public function doAuthorization($sender,$param)
+ {
+ if(!$this->_skipAuthorization)
+ {
+ $this->onAuthorize($param);
+ }
+ }
+
+ public function leave($sender,$param)
+ {
+ if($this->_application->getResponse()->getStatusCode()===401)
+ {
+ $service=$this->_application->getService();
+ if($service instanceof TPageService)
+ {
+ $returnUrl=$this->_application->getRequest()->getRequestUri();
+ $url=$service->constructUrl($this->getLoginPage(),array(self::RETURN_URL_VAR=>$returnUrl));
+ $this->_application->getResponse()->redirect($url);
+ }
+ }
+ }
+
+ public function onAuthenticate($param)
+ {
+ if($this->hasEventHandler('Authenticate'))
+ $this->raiseEvent('Authenticate',$this,$this->_application);
+ if($this->_application->getUser()!==null)
+ return;
+
+ if(($session=$this->_application->getSession())===null)
+ throw new TConfigurationException('authenticator_session_required');
+ $session->open();
+ if(($userManager=$this->getUserManager())===null)
+ throw new TConfigurationException('authenticator_usermanager_required');
+ $sessionInfo=$session->getItems()->itemAt($this->generateUserSessionKey());
+ $user=$userManager->getUser(null)->loadFromString($sessionInfo);
+ $this->_application->setUser($user);
+ }
+
+ public function onAuthorize($param)
+ {
+ if($this->hasEventHandler('Authenticate'))
+ $this->raiseEvent('Authorize',$this,$this->_application);
+ if($this->_authRules!==null && !$this->_authRules->isUserAllowed($this->_application->getUser(),$this->_application->getRequest()->getRequestType()))
+ {
+ $this->_application->getResponse()->setStatusCode(401);
+ $this->_application->completeRequest();
+ }
+ }
+
+ protected function generateUserSessionKey()
+ {
+ return md5($this->_application->getUniqueID().'prado:user');
+ }
+
+ public function updateSessionUser($user)
+ {
+ if(!$user->getIsGuest())
+ {
+ if(($session=$this->_application->getSession())===null)
+ throw new TConfigurationException('authenticator_session_required');
+ else
+ $session->getItems()->add($this->generateUserSessionKey(),$user->saveToString());
+ }
+ }
+
+ public function login($username,$password)
+ {
+ if(($userManager=$this->getUserManager())===null)
+ throw new TConfigurationException('authenticator_usermanager_required');
+ else
+ {
+ if($userManager->validateUser($username,$password))
+ {
+ $user=$userManager->getUser($username);
+ $this->updateSessionUser($user);
+ $this->_application->setUser($user);
+ return true;
+ }
+ else
+ return false;
+ }
+ }
+
+ public function logout()
+ {
+ if(($userManager=$this->getUserManager())===null)
+ throw new TConfigurationException('authenticator_usermanager_required');
+ else if(($session=$this->_application->getSession())===null)
+ throw new TConfigurationException('authenticator_session_required');
+ else
+ {
+ $userManager->logout($this->_application->getUser());
+ $session->destroy();
+ }
+ }
+ /**
+ * @return TAuthorizationRuleCollection list of authorization rules that may be applied
+ */
+
+ public function getAuthorizationRules()
+ {
+ if($this->_authRules===null)
+ $this->_authRules=new TAuthorizationRuleCollection;
+ return $this->_authRules;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/framework/Security/TAuthorizationRule.php b/framework/Security/TAuthorizationRule.php
new file mode 100644
index 00000000..2ee6de49
--- /dev/null
+++ b/framework/Security/TAuthorizationRule.php
@@ -0,0 +1,213 @@
+<?php
+/**
+ * TAuthorizationRule, TAuthorizationRuleCollection class file
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Revision: $ $Date: $
+ * @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), and a verb (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 '*'.
+ * 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.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $ $Date: $
+ * @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 boolean if this rule applies to everyone
+ */
+ private $_everyone;
+ /**
+ * @var boolean if this rule applies to guest user
+ */
+ private $_guest;
+
+ /**
+ * 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'
+ */
+ public function __construct($action,$users,$roles,$verb='')
+ {
+ parent::__construct();
+ $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->_everyone=false;
+ $this->_guest=false;
+ foreach(explode(',',$users) as $user)
+ {
+ if(($user=trim(strtolower($user)))!=='')
+ {
+ if($user==='*')
+ $this->_everyone=true;
+ else if($user==='?')
+ $this->_guest=true;
+ else
+ $this->_users[]=$user;
+ }
+ }
+ foreach(explode(',',$roles) as $role)
+ {
+ if(($role=trim(strtolower($role)))!=='')
+ $this->_roles[]=$role;
+ }
+ $verb=trim(strtolower($verb));
+ if($verb==='' || $verb==='get' || $verb==='post')
+ $this->_verb=$verb;
+ else
+ throw new TInvalidDataValueException('authorizationrule_verb_invalid',$verb);
+ }
+
+ /**
+ * @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 boolean if this rule applies to everyone
+ */
+ public function getGuestApplied()
+ {
+ return $this->_guest;
+ }
+
+ /**
+ * @var boolean if this rule applies to everyone
+ */
+ public function getEveryoneApplied()
+ {
+ return $this->_everyone;
+ }
+
+ /**
+ * @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)
+ {
+ $decision=($this->_action==='allow')?1:-1;
+ if($this->_verb==='' || strcasecmp($verb,$this->_verb)===0)
+ {
+ if($this->_everyone || ($this->_guest && $user->getIsGuest()))
+ return $decision;
+ if(in_array(strtolower($user->getName()),$this->_users))
+ return $decision;
+ foreach($this->_roles as $role)
+ if($user->isInRole($role))
+ return $decision;
+ }
+ return 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 $Revision: $ $Date: $
+ * @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'.
+ * @return boolean whether the user is allowed
+ */
+ public function isUserAllowed($user,$verb)
+ {
+ if($user instanceof IUser)
+ {
+ $verb=strtolower(trim($verb));
+ foreach($this as $rule)
+ {
+ if(($decision=$rule->isUserAllowed($user,$verb))!==0)
+ return ($decision>0);
+ }
+ return true;
+ }
+ else
+ return false;
+ }
+
+ /**
+ * Ensures that only instance of TAuthorizationRule is added to the collection.
+ * @param mixed item to be added to the collection
+ * @return boolean whether the item can be added to the collection
+ */
+ protected function canAddItem($item)
+ {
+ return ($item instanceof TAuthorizationRule);
+ }
+}
+
+?> \ No newline at end of file
diff --git a/framework/Security/TMembershipManager.php b/framework/Security/TMembershipManager.php
new file mode 100644
index 00000000..a3c1ae55
--- /dev/null
+++ b/framework/Security/TMembershipManager.php
@@ -0,0 +1,109 @@
+<?php
+
+
+interface IMembershipUser
+{
+ public function getEmail();
+ public function setEmail($value);
+ public function getCreationDate();
+ public function setCreationDate($value);
+ public function getIsApproved();
+ public function setIsApproved($value);
+ public function getIsLockedOut();
+ public function setIsLockedOut($value);
+ public function getIsOnline();
+ public function setIsOnline($value);
+ public function getLastLoginDate();
+ public function setLastLoginDate($value);
+ public function getLastActivityDate();
+ public function setLastActivityDate($value);
+ public function getLastLockoutDate();
+ public function setLastLockoutDate($value);
+ public function getLastPasswordChangedDate();
+ public function setLastPasswordChangedDate($value);
+ public function getPasswordQuestion();
+ public function setPasswordQuestion($value);
+ public function getComment();
+ public function setComment($value);
+
+ public function update();
+ public function fetchPassword($passwordAnswer=null);
+ public function changePassword($username,$oldPassword,$newPassword);
+ public function changePasswordQuestionAndAnswer($username,$password,$newQuestion,$newAnswer);
+ public function resetPassword($passwordAnswer=null);
+}
+
+interface IUserManager
+{
+}
+
+
+
+class TMembershipUser extends TUser implements IMembershipUser
+{
+}
+
+interface IRoleProvider
+{
+ public function addUsersToRoles($users,$roles);
+ public function removeUsersFromRoles($users,$roles);
+ public function createRole($role);
+ public function deleteRole($role,$throwOnPopulatedRole);
+ public function getAllRoles();
+ public function getRolesForUser($user);
+ public function getUsersInRole($role);
+ public function isUserInRole($user,$role);
+ public function roleExists($role);
+}
+
+interface IMembershipProvider
+{
+ public function getApplicationName();
+ public function setApplicationName($value);
+
+ public function createUser($username,$password,$email,$question,$answer,$isApproved); // return $key or error status
+ public function deleteUser($username,$deleteAllRelatedData);
+ public function updateUser($user);
+
+ public function changePassword($username,$oldPassword,$newPassword);
+ public function changePasswordQuestionAndAnswer($username,$password,$newQuestion,$newAnswer);
+
+ public function encryptPassword($password);
+ public function decryptPassword($encodedPassword);
+ public function encodePassword($password,$format,$salt);
+ public function decodePassword($password,$format);
+ public function generateSalt();
+
+ public function findUsersByEmail($email,$pageIndex,$pageSize);
+ public function findUsersByName($email,$pageIndex,$pageSize);
+
+ public function getAllUsers($pageIndex,$pageSize);
+ public function getUser($username,$userkey,$userIsOnline);
+ public function getNumberOfUsersOnline(); //???
+ public function getUsernameByEmail($email);
+ public function getPassword($username,$answer);
+ public function resetPassword($username,$answer);
+ public function unlockUser($username);
+
+ public function validateUser($username,$password);
+
+ public function onValidatingPassword($param);
+
+ public function getEnablePasswordReset();
+ public function setEnablePasswordReset($value);
+ public function getEnablePasswordRetrieval();
+ public function setEnablePasswordRetrieval($value);
+ public function getMaxInvalidPasswordAttempts();
+ public function setMaxInvalidPasswordAttempts($value);
+ public function getUsernameFormat();
+ public function setUsernameFormat($value);
+ public function getPasswordFormat();
+ public function setPasswordFormat($value);
+ public function getRequiresQuestionAndAnswer();
+ public function setRequiresQuestionAndAnswer($value);
+ public function getRequiresUniqueEmail();
+ public function setRequiresUniqueEmail($value);
+}
+
+
+?> \ No newline at end of file
diff --git a/framework/Security/TStaticMembershipProvider.php b/framework/Security/TStaticMembershipProvider.php
new file mode 100644
index 00000000..857a8f26
--- /dev/null
+++ b/framework/Security/TStaticMembershipProvider.php
@@ -0,0 +1,324 @@
+using System;
+using System.Xml;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Configuration.Provider;
+using System.Web.Security;
+using System.Web.Hosting;
+using System.Web.Management;
+using System.Security.Permissions;
+using System.Web;
+
+public class ReadOnlyXmlMembershipProvider : MembershipProvider
+{
+ private Dictionary<string, MembershipUser> _Users;
+ private string _XmlFileName;
+
+ // MembershipProvider Properties
+ public override string ApplicationName
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+
+ public override bool EnablePasswordRetrieval
+ {
+ get { return false; }
+ }
+
+ public override bool EnablePasswordReset
+ {
+ get { return false; }
+ }
+
+ public override int MaxInvalidPasswordAttempts
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override int MinRequiredNonAlphanumericCharacters
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override int MinRequiredPasswordLength
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override int PasswordAttemptWindow
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override MembershipPasswordFormat PasswordFormat
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override string PasswordStrengthRegularExpression
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override bool RequiresQuestionAndAnswer
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override bool RequiresUniqueEmail
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ // MembershipProvider Methods
+ public override void Initialize (string name,
+ NameValueCollection config)
+ {
+ // Verify that config isn't null
+ if (config == null)
+ throw new ArgumentNullException ("config");
+
+ // Assign the provider a default name if it doesn't have one
+ if (String.IsNullOrEmpty (name))
+ name = "ReadOnlyXmlMembershipProvider";
+
+ // Add a default "description" attribute to config if the
+ // attribute doesn't exist or is empty
+ if (string.IsNullOrEmpty (config["description"])) {
+ config.Remove ("description");
+ config.Add ("description",
+ "Read-only XML membership provider");
+ }
+
+ // Call the base class's Initialize method
+ base.Initialize(name, config);
+
+ // Initialize _XmlFileName and make sure the path
+ // is app-relative
+ string path = config["xmlFileName"];
+
+ if (String.IsNullOrEmpty (path))
+ path = "~/App_Data/Users.xml";
+
+ if (!VirtualPathUtility.IsAppRelative(path))
+ throw new ArgumentException
+ ("xmlFileName must be app-relative");
+
+ string fullyQualifiedPath = VirtualPathUtility.Combine
+ (VirtualPathUtility.AppendTrailingSlash
+ (HttpRuntime.AppDomainAppVirtualPath), path);
+
+ _XmlFileName = HostingEnvironment.MapPath(fullyQualifiedPath);
+ config.Remove ("xmlFileName");
+
+ // Make sure we have permission to read the XML data source and
+ // throw an exception if we don't
+ FileIOPermission permission =
+ new FileIOPermission(FileIOPermissionAccess.Read,
+ _XmlFileName);
+ permission.Demand();
+
+ // Throw an exception if unrecognized attributes remain
+ if (config.Count > 0) {
+ string attr = config.GetKey (0);
+ if (!String.IsNullOrEmpty (attr))
+ throw new ProviderException
+ ("Unrecognized attribute: " + attr);
+ }
+ }
+
+ public override bool ValidateUser(string username, string password)
+ {
+ // Validate input parameters
+ if (String.IsNullOrEmpty(username) ||
+ String.IsNullOrEmpty(password))
+ return false;
+
+ try
+ {
+ // Make sure the data source has been loaded
+ ReadMembershipDataStore();
+
+ // Validate the user name and password
+ MembershipUser user;
+ if (_Users.TryGetValue (username, out user))
+ {
+ if (user.Comment == password) // Case-sensitive
+ {
+ // NOTE: A read/write membership provider
+ // would update the user's LastLoginDate here.
+ // A fully featured provider would also fire
+ // an AuditMembershipAuthenticationSuccess
+ // Web event
+ return true;
+ }
+ }
+
+ // NOTE: A fully featured membership provider would
+ // fire an AuditMembershipAuthenticationFailure
+ // Web event here
+ return false;
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ }
+
+ public override MembershipUser GetUser(string username,
+ bool userIsOnline)
+ {
+ // Note: This implementation ignores userIsOnline
+
+ // Validate input parameters
+ if (String.IsNullOrEmpty(username))
+ return null;
+
+ // Make sure the data source has been loaded
+ ReadMembershipDataStore();
+
+ // Retrieve the user from the data source
+ MembershipUser user;
+ if (_Users.TryGetValue (username, out user))
+ return user;
+
+ return null;
+ }
+
+ public override MembershipUserCollection GetAllUsers(int pageIndex,
+ int pageSize, out int totalRecords)
+ {
+ // Note: This implementation ignores pageIndex and pageSize,
+ // and it doesn't sort the MembershipUser objects returned
+
+ // Make sure the data source has been loaded
+ ReadMembershipDataStore();
+
+ MembershipUserCollection users =
+ new MembershipUserCollection();
+
+ foreach (KeyValuePair<string, MembershipUser> pair in _Users)
+ users.Add(pair.Value);
+
+ totalRecords = users.Count;
+ return users;
+ }
+
+ public override int GetNumberOfUsersOnline()
+ {
+ throw new NotSupportedException();
+ }
+
+ public override bool ChangePassword(string username,
+ string oldPassword, string newPassword)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override bool
+ ChangePasswordQuestionAndAnswer(string username,
+ string password, string newPasswordQuestion,
+ string newPasswordAnswer)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override MembershipUser CreateUser(string username,
+ string password, string email, string passwordQuestion,
+ string passwordAnswer, bool isApproved, object providerUserKey,
+ out MembershipCreateStatus status)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override bool DeleteUser(string username,
+ bool deleteAllRelatedData)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override MembershipUserCollection
+ FindUsersByEmail(string emailToMatch, int pageIndex,
+ int pageSize, out int totalRecords)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override MembershipUserCollection
+ FindUsersByName(string usernameToMatch, int pageIndex,
+ int pageSize, out int totalRecords)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override string GetPassword(string username, string answer)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override MembershipUser GetUser(object providerUserKey,
+ bool userIsOnline)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override string GetUserNameByEmail(string email)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override string ResetPassword(string username,
+ string answer)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override bool UnlockUser(string userName)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override void UpdateUser(MembershipUser user)
+ {
+ throw new NotSupportedException();
+ }
+
+ // Helper method
+ private void ReadMembershipDataStore()
+ {
+ lock (this)
+ {
+ if (_Users == null)
+ {
+ _Users = new Dictionary<string, MembershipUser>
+ (16, StringComparer.InvariantCultureIgnoreCase);
+ XmlDocument doc = new XmlDocument();
+ doc.Load(_XmlFileName);
+ XmlNodeList nodes = doc.GetElementsByTagName("User");
+
+ foreach (XmlNode node in nodes)
+ {
+ MembershipUser user = new MembershipUser(
+ Name, // Provider name
+ node["UserName"].InnerText, // Username
+ null, // providerUserKey
+ node["EMail"].InnerText, // Email
+ String.Empty, // passwordQuestion
+ node["Password"].InnerText, // Comment
+ true, // isApproved
+ false, // isLockedOut
+ DateTime.Now, // creationDate
+ DateTime.Now, // lastLoginDate
+ DateTime.Now, // lastActivityDate
+ DateTime.Now, // lastPasswordChangedDate
+ new DateTime(1980, 1, 1) // lastLockoutDate
+ );
+
+ _Users.Add(user.UserName, user);
+ }
+ }
+ }
+ }
+}
+
diff --git a/framework/Security/TUserManager.php b/framework/Security/TUserManager.php
new file mode 100644
index 00000000..882c5d5c
--- /dev/null
+++ b/framework/Security/TUserManager.php
@@ -0,0 +1,192 @@
+<?php
+
+/**
+ * IUser interface.
+ *
+ * This interface must be implemented by user objects.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $ $Date: $
+ * @package System.Security
+ * @since 3.0
+ */
+interface IUser
+{
+ public function getManager();
+ public function getName();
+ public function setName($value);
+ public function getIsGuest();
+ public function setIsGuest($value);
+ public function getRoles();
+ public function setRoles($value);
+ /**
+ * @param string role to be tested
+ * @return boolean whether the user is of this role
+ */
+ public function isInRole($role);
+ public function saveToString();
+ public function loadFromString($string);
+}
+
+class TUser extends TComponent implements IUser
+{
+ private $_manager;
+ private $_isGuest=false;
+ private $_name='';
+ private $_roles=array();
+
+ public function __construct($manager=null)
+ {
+ parent::__construct();
+ $this->_manager=$manager;
+ }
+
+ public function getManager()
+ {
+ return $this->_manager;
+ }
+
+ public function getName()
+ {
+ return $this->_name;
+ }
+
+ public function setName($value)
+ {
+ $this->_name=$value;
+ }
+
+ public function getIsGuest()
+ {
+ return $this->_isGuest;
+ }
+
+ public function setIsGuest($value)
+ {
+ $this->_isGuest=TPropertyValue::ensureBoolean($value);
+ if($this->_isGuest)
+ {
+ $this->_name='';
+ $this->_roles=array();
+ }
+ }
+
+ public function getRoles()
+ {
+ return $this->_roles;
+ }
+
+ public function setRoles($value)
+ {
+ if(is_array($value))
+ $this->_roles=$value;
+ else
+ {
+ $this->_roles=array();
+ foreach(explode(',',$value) as $role)
+ $this->_roles[]=trim($value);
+ }
+ }
+
+ public function isInRole($role)
+ {
+ return in_array($role,$this->_roles);
+ }
+
+ public function saveToString()
+ {
+ return serialize(array($this->_name,$this->_roles,$this->_isGuest));
+ }
+
+ public function loadFromString($data)
+ {
+ if(!empty($data))
+ {
+ $array=unserialize($data);
+ $this->_name=$array[0];
+ $this->_roles=$array[1];
+ $this->_isGuest=$array[2];
+ }
+ return $this;
+ }
+}
+
+
+class TUserManager extends TComponent implements IModule
+{
+ private $_id;
+ private $_users=array();
+ private $_guestName='Guest';
+ private $_passwordMode='MD5';
+
+ public function init($application,$config)
+ {
+ foreach($config->getElementsByTagName('user') as $node)
+ $this->_users[$node->getAttribute('name')]=$node->getAttribute('password');
+ }
+
+ public function getID()
+ {
+ return $this->_id;
+ }
+
+ public function setID($value)
+ {
+ $this->_id=$value;
+ }
+
+ public function getGuestName()
+ {
+ return $this->_guestName;
+ }
+
+ public function setGuestName($value)
+ {
+ $this->_guestName=$value;
+ }
+
+ public function getPasswordMode()
+ {
+ return $this->_passwordMode;
+ }
+
+ public function setPasswordMode($value)
+ {
+ $this->_passwordMode=TPropertyValue::ensureEnum($value,array('Clear','MD5','SHA1'));
+ }
+
+ public function validateUser($username,$password)
+ {
+ if($this->_passwordMode==='MD5')
+ $password=md5($password);
+ else if($this->_passwordMode==='SHA1')
+ $password=sha1($password);
+ return (isset($this->_users[$username]) && $this->_users[$username]===$password);
+ }
+
+ public function logout($user)
+ {
+ $user->setIsGuest(true);
+ $user->setName($this->getGuestName());
+ }
+
+ public function getUser($username=null)
+ {
+ if($username===null)
+ {
+ $user=new TUser($this);
+ $user->setIsGuest($username===null);
+ return $user;
+ }
+ else if(isset($this->_users[$username]))
+ {
+ $user=new TUser($this);
+ $user->setName($username);
+ return $user;
+ }
+ else
+ return null;
+ }
+}
+
+?> \ No newline at end of file