sfBasicSecurityUser.class.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. <?php
  2. /*
  3. * This file is part of the symfony package.
  4. * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
  5. * (c) 2004-2006 Sean Kerr <sean@code-box.org>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. /**
  11. * sfBasicSecurityUser will handle any type of data as a credential.
  12. *
  13. * @package symfony
  14. * @subpackage user
  15. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  16. * @author Sean Kerr <sean@code-box.org>
  17. * @version SVN: $Id: sfBasicSecurityUser.class.php 11694 2008-09-21 08:26:37Z fabien $
  18. */
  19. class sfBasicSecurityUser extends sfUser implements sfSecurityUser
  20. {
  21. const LAST_REQUEST_NAMESPACE = 'symfony/user/sfUser/lastRequest';
  22. const AUTH_NAMESPACE = 'symfony/user/sfUser/authenticated';
  23. const CREDENTIAL_NAMESPACE = 'symfony/user/sfUser/credentials';
  24. protected $lastRequest = null;
  25. protected $credentials = null;
  26. protected $authenticated = null;
  27. protected $timedout = false;
  28. /**
  29. * Clears all credentials.
  30. *
  31. */
  32. public function clearCredentials()
  33. {
  34. $this->credentials = null;
  35. $this->credentials = array();
  36. }
  37. /**
  38. * returns an array containing the credentials
  39. */
  40. public function listCredentials()
  41. {
  42. return $this->credentials;
  43. }
  44. /**
  45. * Removes a credential.
  46. *
  47. * @param mixed credential
  48. */
  49. public function removeCredential($credential)
  50. {
  51. if ($this->hasCredential($credential))
  52. {
  53. foreach ($this->credentials as $key => $value)
  54. {
  55. if ($credential == $value)
  56. {
  57. if ($this->options['logging'])
  58. {
  59. $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Remove credential "%s"', $credential))));
  60. }
  61. unset($this->credentials[$key]);
  62. $this->storage->regenerate(false);
  63. return;
  64. }
  65. }
  66. }
  67. }
  68. /**
  69. * Adds a credential.
  70. *
  71. * @param mixed $credential
  72. */
  73. public function addCredential($credential)
  74. {
  75. $this->addCredentials(func_get_args());
  76. }
  77. /**
  78. * Adds several credential at once.
  79. *
  80. * @param mixed array or list of credentials
  81. */
  82. public function addCredentials()
  83. {
  84. if (func_num_args() == 0) return;
  85. // Add all credentials
  86. $credentials = (is_array(func_get_arg(0))) ? func_get_arg(0) : func_get_args();
  87. if ($this->options['logging'])
  88. {
  89. $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Add credential(s) "%s"', implode(', ', $credentials)))));
  90. }
  91. $added = false;
  92. foreach ($credentials as $aCredential)
  93. {
  94. if (!in_array($aCredential, $this->credentials))
  95. {
  96. $added = true;
  97. $this->credentials[] = $aCredential;
  98. }
  99. }
  100. if ($added)
  101. {
  102. $this->storage->regenerate(false);
  103. }
  104. }
  105. /**
  106. * Returns true if user has credential.
  107. *
  108. * @param mixed $credentials
  109. * @param bool $useAnd specify the mode, either AND or OR
  110. * @return bool
  111. *
  112. * @author Olivier Verdier <Olivier.Verdier@free.fr>
  113. */
  114. public function hasCredential($credentials, $useAnd = true)
  115. {
  116. if (!is_array($credentials))
  117. {
  118. return in_array($credentials, $this->credentials);
  119. }
  120. // now we assume that $credentials is an array
  121. $test = false;
  122. foreach ($credentials as $credential)
  123. {
  124. // recursively check the credential with a switched AND/OR mode
  125. $test = $this->hasCredential($credential, $useAnd ? false : true);
  126. if ($useAnd)
  127. {
  128. $test = $test ? false : true;
  129. }
  130. if ($test) // either passed one in OR mode or failed one in AND mode
  131. {
  132. break; // the matter is settled
  133. }
  134. }
  135. if ($useAnd) // in AND mode we succeed if $test is false
  136. {
  137. $test = $test ? false : true;
  138. }
  139. return $test;
  140. }
  141. /**
  142. * Returns true if user is authenticated.
  143. *
  144. * @return boolean
  145. */
  146. public function isAuthenticated()
  147. {
  148. return $this->authenticated;
  149. }
  150. /**
  151. * Sets authentication for user.
  152. *
  153. * @param bool $authenticated
  154. */
  155. public function setAuthenticated($authenticated)
  156. {
  157. if ($this->options['logging'])
  158. {
  159. $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('User is %sauthenticated', $authenticated === true ? '' : 'not '))));
  160. }
  161. if ((bool) $authenticated !== $this->authenticated)
  162. {
  163. if ($authenticated === true)
  164. {
  165. $this->authenticated = true;
  166. }
  167. else
  168. {
  169. $this->authenticated = false;
  170. $this->clearCredentials();
  171. }
  172. $this->dispatcher->notify(new sfEvent($this, 'user.change_authentication', array('authenticated' => $this->authenticated)));
  173. $this->storage->regenerate(false);
  174. }
  175. }
  176. public function setTimedOut()
  177. {
  178. $this->timedout = true;
  179. }
  180. public function isTimedOut()
  181. {
  182. return $this->timedout;
  183. }
  184. /**
  185. * Returns the timestamp of the last user request.
  186. *
  187. * @param int
  188. */
  189. public function getLastRequestTime()
  190. {
  191. return $this->lastRequest;
  192. }
  193. /**
  194. * Available options:
  195. *
  196. * * timeout: Timeout to automatically log out the user in seconds (1800 by default)
  197. * Set to false to disable
  198. *
  199. * @param sfEventDispatcher $dispatcher An sfEventDispatcher instance.
  200. * @param sfStorage $storage An sfStorage instance.
  201. * @param array $options An associative array of options.
  202. *
  203. * @see sfUser
  204. */
  205. public function initialize(sfEventDispatcher $dispatcher, sfStorage $storage, $options = array())
  206. {
  207. // initialize parent
  208. parent::initialize($dispatcher, $storage, $options);
  209. if (!array_key_exists('timeout', $this->options))
  210. {
  211. $this->options['timeout'] = 1800;
  212. }
  213. // force the max lifetime for session garbage collector to be greater than timeout
  214. if (ini_get('session.gc_maxlifetime') < $this->options['timeout'])
  215. {
  216. ini_set('session.gc_maxlifetime', $this->options['timeout']);
  217. }
  218. // read data from storage
  219. $this->authenticated = $storage->read(self::AUTH_NAMESPACE);
  220. $this->credentials = $storage->read(self::CREDENTIAL_NAMESPACE);
  221. $this->lastRequest = $storage->read(self::LAST_REQUEST_NAMESPACE);
  222. if (is_null($this->authenticated))
  223. {
  224. $this->authenticated = false;
  225. $this->credentials = array();
  226. }
  227. else
  228. {
  229. // Automatic logout logged in user if no request within timeout parameter seconds
  230. $timeout = $this->options['timeout'];
  231. if (false !== $timeout && !is_null($this->lastRequest) && time() - $this->lastRequest >= $timeout)
  232. {
  233. if ($this->options['logging'])
  234. {
  235. $this->dispatcher->notify(new sfEvent($this, 'application.log', array('Automatic user logout due to timeout')));
  236. }
  237. $this->setTimedOut();
  238. $this->setAuthenticated(false);
  239. }
  240. }
  241. $this->lastRequest = time();
  242. }
  243. public function shutdown()
  244. {
  245. // write the last request time to the storage
  246. $this->storage->write(self::LAST_REQUEST_NAMESPACE, $this->lastRequest);
  247. $this->storage->write(self::AUTH_NAMESPACE, $this->authenticated);
  248. $this->storage->write(self::CREDENTIAL_NAMESPACE, $this->credentials);
  249. // call the parent shutdown method
  250. parent::shutdown();
  251. }
  252. }