PageRenderTime 35ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/Nette/Http/User.php

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