PageRenderTime 41ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/Nette/Web/User.php

https://github.com/DocX/nette
PHP | 443 lines | 199 code | 105 blank | 139 comment | 31 complexity | de019568621cda21eef27c15c6dcadb2 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Nette Framework
  4. *
  5. * Copyright (c) 2004, 2009 David Grudl (http://davidgrudl.com)
  6. *
  7. * This source file is subject to the "Nette license" that is bundled
  8. * with this package in the file license.txt.
  9. *
  10. * For more information please see http://nettephp.com
  11. *
  12. * @copyright Copyright (c) 2004, 2009 David Grudl
  13. * @license http://nettephp.com/license Nette license
  14. * @link http://nettephp.com
  15. * @category Nette
  16. * @package Nette\Web
  17. */
  18. /*namespace Nette\Web;*/
  19. /*use Nette\Environment;*/
  20. require_once dirname(__FILE__) . '/../Object.php';
  21. require_once dirname(__FILE__) . '/../Web/IUser.php';
  22. /**
  23. * Authentication and authorization.
  24. *
  25. * @author David Grudl
  26. * @copyright Copyright (c) 2004, 2009 David Grudl
  27. * @package Nette\Web
  28. *
  29. * @property-read Nette\Security\IIdentity $identity
  30. * @property Nette\Security\IAuthenticator $authenticationHandler
  31. * @property Nette\Security\IAuthorizator $authorizationHandler
  32. * @property-read int $signOutReason
  33. * @property-read array $roles
  34. * @property-read bool $authenticated
  35. */
  36. class User extends /*Nette\*/Object implements IUser
  37. {
  38. /**#@+ sign-out reason {@link User::getSignOutReason()} */
  39. const MANUAL = 1;
  40. const INACTIVITY = 2;
  41. const BROWSER_CLOSED = 3;
  42. /**#@-*/
  43. /** @var string default role for unauthenticated user */
  44. public $guestRole = 'guest';
  45. /** @var string default role for authenticated user without own identity */
  46. public $authenticatedRole = 'authenticated';
  47. /** @var array of function(User $sender); Occurs when the user is successfully authenticated */
  48. public $onAuthenticated;
  49. /** @var array of function(User $sender); Occurs when the user is logged off */
  50. public $onSignedOut;
  51. /** @var Nette\Security\IAuthenticator */
  52. private $authenticationHandler;
  53. /** @var Nette\Security\IAuthorizator */
  54. private $authorizationHandler;
  55. /** @var string */
  56. private $namespace = '';
  57. /** @var SessionNamespace */
  58. private $session;
  59. /********************* Authentication ****************d*g**/
  60. /**
  61. * Conducts the authentication process.
  62. * @param string
  63. * @param string
  64. * @param mixed
  65. * @return void
  66. * @throws Nette\Security\AuthenticationException if authentication was not successful
  67. */
  68. public function authenticate($username, $password, $extra = NULL)
  69. {
  70. $handler = $this->getAuthenticationHandler();
  71. if ($handler === NULL) {
  72. throw new /*\*/InvalidStateException('Authentication handler has not been set.');
  73. }
  74. $this->signOut(TRUE);
  75. $credentials = array(
  76. /*Nette\Security\*/IAuthenticator::USERNAME => $username,
  77. /*Nette\Security\*/IAuthenticator::PASSWORD => $password,
  78. 'extra' => $extra,
  79. );
  80. $this->setIdentity($handler->authenticate($credentials));
  81. $this->setAuthenticated(TRUE);
  82. $this->onAuthenticated($this);
  83. }
  84. /**
  85. * Logs off the user from the current session.
  86. * @param bool clear the identity from persistent storage?
  87. * @return void
  88. */
  89. final public function signOut($clearIdentity = FALSE)
  90. {
  91. if ($this->isAuthenticated()) {
  92. $this->setAuthenticated(FALSE);
  93. $this->onSignedOut($this);
  94. }
  95. if ($clearIdentity) {
  96. $this->setIdentity(NULL);
  97. }
  98. }
  99. /**
  100. * Is this user authenticated?
  101. * @return bool
  102. */
  103. final public function isAuthenticated()
  104. {
  105. $session = $this->getSessionNamespace(FALSE);
  106. return $session && $session->authenticated;
  107. }
  108. /**
  109. * Returns current user identity, if any.
  110. * @return Nette\Security\IIdentity
  111. */
  112. final public function getIdentity()
  113. {
  114. $session = $this->getSessionNamespace(FALSE);
  115. return $session ? $session->identity : NULL;
  116. }
  117. /**
  118. * Sets authentication handler.
  119. * @param Nette\Security\IAuthenticator
  120. * @return User provides a fluent interface
  121. */
  122. public function setAuthenticationHandler(/*Nette\Security\*/IAuthenticator $handler)
  123. {
  124. $this->authenticationHandler = $handler;
  125. return $this;
  126. }
  127. /**
  128. * Returns authentication handler.
  129. * @return Nette\Security\IAuthenticator
  130. */
  131. final public function getAuthenticationHandler()
  132. {
  133. if ($this->authenticationHandler === NULL) {
  134. $this->authenticationHandler = Environment::getService('Nette\Security\IAuthenticator');
  135. }
  136. return $this->authenticationHandler;
  137. }
  138. /**
  139. * Changes namespace; allows more users to share a session.
  140. * @param string
  141. * @return User provides a fluent interface
  142. */
  143. public function setNamespace($namespace)
  144. {
  145. if ($this->namespace !== $namespace) {
  146. $this->namespace = (string) $namespace;
  147. $this->session = NULL;
  148. }
  149. return $this;
  150. }
  151. /**
  152. * Returns current namespace.
  153. * @return string
  154. */
  155. final public function getNamespace()
  156. {
  157. return $this->namespace;
  158. }
  159. /**
  160. * Enables sign out after inactivity.
  161. * @param mixed number of seconds or timestamp
  162. * @param bool sign out when the browser is closed?
  163. * @param bool clear the identity from persistent storage?
  164. * @return User provides a fluent interface
  165. */
  166. public function setExpiration($seconds, $whenBrowserIsClosed = TRUE, $clearIdentity = FALSE)
  167. {
  168. if (is_string($seconds) && !is_numeric($seconds)) {
  169. $seconds = strtotime($seconds);
  170. }
  171. $session = $this->getSessionNamespace(TRUE);
  172. if ($seconds > 0) {
  173. if ($seconds <= /*Nette\*/Tools::YEAR) {
  174. $seconds += time();
  175. }
  176. $session->expireTime = $seconds;
  177. $session->expireDelta = $seconds - time();
  178. } else {
  179. unset($session->expireTime, $session->expireDelta);
  180. }
  181. $session->expireIdentity = (bool) $clearIdentity;
  182. $session->expireBrowser = (bool) $whenBrowserIsClosed;
  183. $session->browserCheck = TRUE;
  184. $session->setExpiration(0, 'browserCheck');
  185. return $this;
  186. }
  187. /**
  188. * Why was user signed out?
  189. * @return int
  190. */
  191. final public function getSignOutReason()
  192. {
  193. $session = $this->getSessionNamespace(FALSE);
  194. return $session ? $session->reason : NULL;
  195. }
  196. /**
  197. * Returns and initializes $this->session.
  198. * @return SessionNamespace
  199. */
  200. protected function getSessionNamespace($need)
  201. {
  202. if ($this->session !== NULL) {
  203. return $this->session;
  204. }
  205. $sessionHandler = $this->getSession();
  206. if (!$need && !$sessionHandler->exists()) {
  207. return NULL;
  208. }
  209. $this->session = $session = $sessionHandler->getNamespace('Nette.Web.User/' . $this->namespace);
  210. if (!($session->identity instanceof /*Nette\Security\*/IIdentity) || !is_bool($session->authenticated)) {
  211. $session->remove();
  212. }
  213. if ($session->authenticated && $session->expireBrowser && !$session->browserCheck) { // check if browser was closed?
  214. $session->reason = self::BROWSER_CLOSED;
  215. $session->authenticated = FALSE;
  216. $this->onSignedOut($this);
  217. if ($session->expireIdentity) {
  218. unset($session->identity);
  219. }
  220. }
  221. if ($session->authenticated && $session->expireDelta > 0) { // check time expiration
  222. if ($session->expireTime < time()) {
  223. $session->reason = self::INACTIVITY;
  224. $session->authenticated = FALSE;
  225. $this->onSignedOut($this);
  226. if ($session->expireIdentity) {
  227. unset($session->identity);
  228. }
  229. }
  230. $session->expireTime = time() + $session->expireDelta; // sliding expiration
  231. }
  232. if (!$session->authenticated) {
  233. unset($session->expireTime, $session->expireDelta, $session->expireIdentity,
  234. $session->expireBrowser, $session->browserCheck, $session->authTime);
  235. }
  236. return $this->session;
  237. }
  238. /**
  239. * Sets the authenticated status of this user.
  240. * @param bool flag indicating the authenticated status of user
  241. * @return User provides a fluent interface
  242. */
  243. protected function setAuthenticated($state)
  244. {
  245. $session = $this->getSessionNamespace(TRUE);
  246. $session->authenticated = (bool) $state;
  247. // Session Fixation defence
  248. $this->getSession()->regenerateId();
  249. if ($state) {
  250. $session->reason = NULL;
  251. $session->authTime = time(); // informative value
  252. } else {
  253. $session->reason = self::MANUAL;
  254. $session->authTime = NULL;
  255. }
  256. return $this;
  257. }
  258. /**
  259. * Sets the user identity.
  260. * @param IIdentity
  261. * @return User provides a fluent interface
  262. */
  263. protected function setIdentity(/*Nette\Security\*/IIdentity $identity = NULL)
  264. {
  265. $this->getSessionNamespace(TRUE)->identity = $identity;
  266. return $this;
  267. }
  268. /********************* Authorization ****************d*g**/
  269. /**
  270. * Returns a list of effective roles that a user has been granted.
  271. * @return array
  272. */
  273. public function getRoles()
  274. {
  275. if (!$this->isAuthenticated()) {
  276. return array($this->guestRole);
  277. }
  278. $identity = $this->getIdentity();
  279. return $identity ? $identity->getRoles() : array($this->authenticatedRole);
  280. }
  281. /**
  282. * Is a user in the specified effective role?
  283. * @param string
  284. * @return bool
  285. */
  286. final public function isInRole($role)
  287. {
  288. return in_array($role, $this->getRoles(), TRUE);
  289. }
  290. /**
  291. * Has a user effective access to the Resource?
  292. * If $resource is NULL, then the query applies to all resources.
  293. * @param string resource
  294. * @param string privilege
  295. * @return bool
  296. */
  297. public function isAllowed($resource = NULL, $privilege = NULL)
  298. {
  299. $handler = $this->getAuthorizationHandler();
  300. if (!$handler) {
  301. throw new /*\*/InvalidStateException("Authorization handler has not been set.");
  302. }
  303. foreach ($this->getRoles() as $role) {
  304. if ($handler->isAllowed($role, $resource, $privilege)) return TRUE;
  305. }
  306. return FALSE;
  307. }
  308. /**
  309. * Sets authorization handler.
  310. * @param Nette\Security\IAuthorizator
  311. * @return User provides a fluent interface
  312. */
  313. public function setAuthorizationHandler(/*Nette\Security\*/IAuthorizator $handler)
  314. {
  315. $this->authorizationHandler = $handler;
  316. return $this;
  317. }
  318. /**
  319. * Returns current authorization handler.
  320. * @return Nette\Security\IAuthorizator
  321. */
  322. final public function getAuthorizationHandler()
  323. {
  324. if ($this->authorizationHandler === NULL) {
  325. $this->authorizationHandler = Environment::getService('Nette\Security\IAuthorizator');
  326. }
  327. return $this->authorizationHandler;
  328. }
  329. /********************* backend ****************d*g**/
  330. /**
  331. * Returns session handler.
  332. * @return Nette\Web\Session
  333. */
  334. protected function getSession()
  335. {
  336. return Environment::getSession();
  337. }
  338. }