Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * TUserManager class
4
 *
5
 * @author Qiang Xue <qiang.xue@gmail.com>
6
 * @link http://www.pradosoft.com/
7
 * @copyright Copyright &copy; 2005-2008 PradoSoft
8
 * @license http://www.pradosoft.com/license/
9
 * @version $Id: TUserManager.php 2541 2008-10-21 15:05:13Z qiang.xue $
10
 * @package System.Security
11
 */
12
 
13
/**
14
 * Using TUser class
15
 */
16
Prado::using('System.Security.TUser');
17
 
18
/**
19
 * TUserManager class
20
 *
21
 * TUserManager manages a static list of users {@link TUser}.
22
 * The user information is specified via module configuration using the following XML syntax,
23
 * <code>
24
 * <module id="users" class="System.Security.TUserManager" PasswordMode="Clear">
25
 *   <user name="Joe" password="demo" />
26
 *   <user name="John" password="demo" />
27
 *   <role name="Administrator" users="John" />
28
 *   <role name="Writer" users="Joe,John" />
29
 * </module>
30
 * </code>
31
 *
32
 * In addition, user information can also be loaded from an external file
33
 * specified by {@link setUserFile UserFile} property. Note, the property
34
 * only accepts a file path in namespace format. The user file format is
35
 * similar to the above sample.
36
 *
37
 * The user passwords may be specified as clear text, SH1 or MD5 hashed by setting
38
 * {@link setPasswordMode PasswordMode} as <b>Clear</b>, <b>SHA1</b> or <b>MD5</b>.
39
 * The default name for a guest user is <b>Guest</b>. It may be changed
40
 * by setting {@link setGuestName GuestName} property.
41
 *
42
 * TUserManager may be used together with {@link TAuthManager} which manages
43
 * how users are authenticated and authorized in a Prado application.
44
 *
45
 * @author Qiang Xue <qiang.xue@gmail.com>
46
 * @version $Id: TUserManager.php 2541 2008-10-21 15:05:13Z qiang.xue $
47
 * @package System.Security
48
 * @since 3.0
49
 */
50
class TUserManager extends TModule implements IUserManager
51
{
52
	/**
53
	 * extension name to the user file
54
	 */
55
	const USER_FILE_EXT='.xml';
56
 
57
	/**
58
	 * @var array list of users managed by this module
59
	 */
60
	private $_users=array();
61
	/**
62
	 * @var array list of roles managed by this module
63
	 */
64
	private $_roles=array();
65
	/**
66
	 * @var string guest name
67
	 */
68
	private $_guestName='Guest';
69
	/**
70
	 * @var TUserManagerPasswordMode password mode
71
	 */
72
	private $_passwordMode=TUserManagerPasswordMode::MD5;
73
	/**
74
	 * @var boolean whether the module has been initialized
75
	 */
76
	private $_initialized=false;
77
	/**
78
	 * @var string user/role information file
79
	 */
80
	private $_userFile=null;
81
 
82
	/**
83
	 * Initializes the module.
84
	 * This method is required by IModule and is invoked by application.
85
	 * It loads user/role information from the module configuration.
86
	 * @param TXmlElement module configuration
87
	 */
88
	public function init($config)
89
	{
90
		$this->loadUserData($config);
91
		if($this->_userFile!==null)
92
		{
93
			$dom=new TXmlDocument;
94
			$dom->loadFromFile($this->_userFile);
95
			$this->loadUserData($dom);
96
		}
97
		$this->_initialized=true;
98
	}
99
 
100
	/**
101
	 * Loads user/role information from an XML node.
102
	 * @param TXmlElement the XML node containing the user information
103
	 */
104
	protected function loadUserData($xmlNode)
105
	{
106
		foreach($xmlNode->getElementsByTagName('user') as $node)
107
		{
108
			$name=trim(strtolower($node->getAttribute('name')));
109
			$this->_users[$name]=$node->getAttribute('password');
110
			if(($roles=trim($node->getAttribute('roles')))!=='')
111
			{
112
				foreach(explode(',',$roles) as $role)
113
				{
114
					if(($role=trim($role))!=='')
115
						$this->_roles[$name][]=$role;
116
				}
117
			}
118
		}
119
		foreach($xmlNode->getElementsByTagName('role') as $node)
120
		{
121
			foreach(explode(',',$node->getAttribute('users')) as $user)
122
			{
123
				if(($user=trim($user))!=='')
124
					$this->_roles[strtolower($user)][]=$node->getAttribute('name');
125
			}
126
		}
127
	}
128
 
129
	/**
130
	 * Returns an array of all users.
131
	 * Each array element represents a single user.
132
	 * The array key is the username in lower case, and the array value is the
133
	 * corresponding user password.
134
	 * @return array list of users
135
	 */
136
	public function getUsers()
137
	{
138
		return $this->_users;
139
	}
140
 
141
	/**
142
	 * Returns an array of user role information.
143
	 * Each array element represents the roles for a single user.
144
	 * The array key is the username in lower case, and the array value is
145
	 * the roles (represented as an array) that the user is in.
146
	 * @return array list of user role information
147
	 */
148
	public function getRoles()
149
	{
150
		return $this->_roles;
151
	}
152
 
153
	/**
154
	 * @return string the full path to the file storing user/role information
155
	 */
156
	public function getUserFile()
157
	{
158
		return $this->_userFile;
159
	}
160
 
161
	/**
162
	 * @param string user/role data file path (in namespace form). The file format is XML
163
	 * whose content is similar to that user/role block in application configuration.
164
	 * @throws TInvalidOperationException if the module is already initialized
165
	 * @throws TConfigurationException if the file is not in proper namespace format
166
	 */
167
	public function setUserFile($value)
168
	{
169
		if($this->_initialized)
170
			throw new TInvalidOperationException('usermanager_userfile_unchangeable');
171
		else if(($this->_userFile=Prado::getPathOfNamespace($value,self::USER_FILE_EXT))===null || !is_file($this->_userFile))
172
			throw new TConfigurationException('usermanager_userfile_invalid',$value);
173
	}
174
 
175
	/**
176
	 * @return string guest name, defaults to 'Guest'
177
	 */
178
	public function getGuestName()
179
	{
180
		return $this->_guestName;
181
	}
182
 
183
	/**
184
	 * @param string name to be used for guest users.
185
	 */
186
	public function setGuestName($value)
187
	{
188
		$this->_guestName=$value;
189
	}
190
 
191
	/**
192
	 * @return TUserManagerPasswordMode how password is stored, clear text, or MD5 or SHA1 hashed. Default to TUserManagerPasswordMode::MD5.
193
	 */
194
	public function getPasswordMode()
195
	{
196
		return $this->_passwordMode;
197
	}
198
 
199
	/**
200
	 * @param TUserManagerPasswordMode how password is stored, clear text, or MD5 or SHA1 hashed.
201
	 */
202
	public function setPasswordMode($value)
203
	{
204
		$this->_passwordMode=TPropertyValue::ensureEnum($value,'TUserManagerPasswordMode');
205
	}
206
 
207
	/**
208
	 * Validates if the username and password are correct.
209
	 * @param string user name
210
	 * @param string password
211
	 * @return boolean true if validation is successful, false otherwise.
212
	 */
213
	public function validateUser($username,$password)
214
	{
215
		if($this->_passwordMode===TUserManagerPasswordMode::MD5)
216
			$password=md5($password);
217
		else if($this->_passwordMode===TUserManagerPasswordMode::SHA1)
218
			$password=sha1($password);
219
		$username=strtolower($username);
220
		return (isset($this->_users[$username]) && $this->_users[$username]===$password);
221
	}
222
 
223
	/**
224
	 * Returns a user instance given the user name.
225
	 * @param string user name, null if it is a guest.
226
	 * @return TUser the user instance, null if the specified username is not in the user database.
227
	 */
228
	public function getUser($username=null)
229
	{
230
		if($username===null)
231
		{
232
			$user=new TUser($this);
233
			$user->setIsGuest(true);
234
			return $user;
235
		}
236
		else
237
		{
238
			$username=strtolower($username);
239
			if(isset($this->_users[$username]))
240
			{
241
				$user=new TUser($this);
242
				$user->setName($username);
243
				$user->setIsGuest(false);
244
				if(isset($this->_roles[$username]))
245
					$user->setRoles($this->_roles[$username]);
246
				return $user;
247
			}
248
			else
249
				return null;
250
		}
251
	}
252
 
253
	/**
254
	 * Returns a user instance according to auth data stored in a cookie.
255
	 * @param THttpCookie the cookie storing user authentication information
256
	 * @return TUser the user instance generated based on the cookie auth data, null if the cookie does not have valid auth data.
257
	 * @since 3.1.1
258
	 */
259
	public function getUserFromCookie($cookie)
260
	{
261
		if(($data=$cookie->getValue())!=='')
262
		{
263
			$data=unserialize($data);
264
			if(is_array($data) && count($data)===2)
265
			{
266
				list($username,$token)=$data;
267
				if(isset($this->_users[$username]) && $token===md5($username.$this->_users[$username]))
268
					return $this->getUser($username);
269
			}
270
		}
271
		return null;
272
	}
273
 
274
	/**
275
	 * Saves user auth data into a cookie.
276
	 * @param THttpCookie the cookie to receive the user auth data.
277
	 * @since 3.1.1
278
	 */
279
	public function saveUserToCookie($cookie)
280
	{
281
		$user=$this->getApplication()->getUser();
282
		$username=strtolower($user->getName());
283
		if(isset($this->_users[$username]))
284
		{
285
			$data=array($username,md5($username.$this->_users[$username]));
286
			$cookie->setValue(serialize($data));
287
		}
288
	}
289
 
290
	/**
291
	 * Sets a user as a guest.
292
	 * User name is changed as guest name, and roles are emptied.
293
	 * @param TUser the user to be changed to a guest.
294
	 */
295
	public function switchToGuest($user)
296
	{
297
		$user->setIsGuest(true);
298
	}
299
}
300
 
301
/**
302
 * TUserManagerPasswordMode class.
303
 * TUserManagerPasswordMode defines the enumerable type for the possible modes
304
 * that user passwords can be specified for a {@link TUserManager}.
305
 *
306
 * The following enumerable values are defined:
307
 * - Clear: the password is in plain text
308
 * - MD5: the password is recorded as the MD5 hash value of the original password
309
 * - SHA1: the password is recorded as the SHA1 hash value of the original password
310
 *
311
 * @author Qiang Xue <qiang.xue@gmail.com>
312
 * @version $Id: TUserManager.php 2541 2008-10-21 15:05:13Z qiang.xue $
313
 * @package System.Security
314
 * @since 3.0.4
315
 */
316
class TUserManagerPasswordMode extends TEnumerable
317
{
318
	const Clear='Clear';
319
	const MD5='MD5';
320
	const SHA1='SHA1';
321
}
322