1: <?php
2:
3: /**
4: * This file is part of the Nette Framework (https://nette.org)
5: * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
6: * @package Nette\Http
7: */
8:
9:
10:
11: /**
12: * Session storage for user object.
13: *
14: * @author David Grudl
15: * @author Jan Tichý
16: * @package Nette\Http
17: */
18: class UserStorage extends Object implements IUserStorage
19: {
20: /** @var string */
21: private $namespace = '';
22:
23: /** @var Session */
24: private $sessionHandler;
25:
26: /** @var SessionSection */
27: private $sessionSection;
28:
29:
30: public function __construct(Session $sessionHandler)
31: {
32: $this->sessionHandler = $sessionHandler;
33: }
34:
35:
36: /**
37: * Sets the authenticated status of this user.
38: * @param bool
39: * @return self
40: */
41: public function setAuthenticated($state)
42: {
43: $section = $this->getSessionSection(TRUE);
44: $section->authenticated = (bool) $state;
45:
46: // Session Fixation defence
47: $this->sessionHandler->regenerateId();
48:
49: if ($state) {
50: $section->reason = NULL;
51: $section->authTime = time(); // informative value
52:
53: } else {
54: $section->reason = self::MANUAL;
55: $section->authTime = NULL;
56: }
57: return $this;
58: }
59:
60:
61: /**
62: * Is this user authenticated?
63: * @return bool
64: */
65: public function isAuthenticated()
66: {
67: $session = $this->getSessionSection(FALSE);
68: return $session && $session->authenticated;
69: }
70:
71:
72: /**
73: * Sets the user identity.
74: * @return self
75: */
76: public function setIdentity(IIdentity $identity = NULL)
77: {
78: $this->getSessionSection(TRUE)->identity = $identity;
79: return $this;
80: }
81:
82:
83: /**
84: * Returns current user identity, if any.
85: * @return IIdentity|NULL
86: */
87: public function getIdentity()
88: {
89: $session = $this->getSessionSection(FALSE);
90: return $session ? $session->identity : NULL;
91: }
92:
93:
94: /**
95: * Changes namespace; allows more users to share a session.
96: * @param string
97: * @return self
98: */
99: public function setNamespace($namespace)
100: {
101: if ($this->namespace !== $namespace) {
102: $this->namespace = (string) $namespace;
103: $this->sessionSection = NULL;
104: }
105: return $this;
106: }
107:
108:
109: /**
110: * Returns current namespace.
111: * @return string
112: */
113: public function getNamespace()
114: {
115: return $this->namespace;
116: }
117:
118:
119: /**
120: * Enables log out after inactivity.
121: * @param string|int|DateTime Number of seconds or timestamp
122: * @param int Log out when the browser is closed | Clear the identity from persistent storage?
123: * @return self
124: */
125: public function setExpiration($time, $flags = 0)
126: {
127: $section = $this->getSessionSection(TRUE);
128: if ($time) {
129: $time = DateTime53::from($time)->format('U');
130: $section->expireTime = $time;
131: $section->expireDelta = $time - time();
132:
133: } else {
134: unset($section->expireTime, $section->expireDelta);
135: }
136:
137: $section->expireIdentity = (bool) ($flags & self::CLEAR_IDENTITY);
138: $section->expireBrowser = (bool) ($flags & self::BROWSER_CLOSED);
139: $section->browserCheck = TRUE;
140: $section->setExpiration(0, 'browserCheck');
141: $section->setExpiration($time, 'foo'); // time check
142: return $this;
143: }
144:
145:
146: /**
147: * Why was user logged out?
148: * @return int
149: */
150: public function getLogoutReason()
151: {
152: $session = $this->getSessionSection(FALSE);
153: return $session ? $session->reason : NULL;
154: }
155:
156:
157: /**
158: * Returns and initializes $this->sessionSection.
159: * @return SessionSection
160: */
161: protected function getSessionSection($need)
162: {
163: if ($this->sessionSection !== NULL) {
164: return $this->sessionSection;
165: }
166:
167: if (!$need && !$this->sessionHandler->exists()) {
168: return NULL;
169: }
170:
171: $this->sessionSection = $section = $this->sessionHandler->getSection('Nette.Http.UserStorage/' . $this->namespace);
172:
173: if (!$section->identity instanceof IIdentity || !is_bool($section->authenticated)) {
174: $section->remove();
175: }
176:
177: if ($section->authenticated && $section->expireBrowser && !$section->browserCheck) { // check if browser was closed?
178: $section->reason = self::BROWSER_CLOSED;
179: $section->authenticated = FALSE;
180: if ($section->expireIdentity) {
181: unset($section->identity);
182: }
183: }
184:
185: if ($section->authenticated && $section->expireDelta > 0) { // check time expiration
186: if ($section->expireTime < time()) {
187: $section->reason = self::INACTIVITY;
188: $section->authenticated = FALSE;
189: if ($section->expireIdentity) {
190: unset($section->identity);
191: }
192: }
193: $section->expireTime = time() + $section->expireDelta; // sliding expiration
194: }
195:
196: if (!$section->authenticated) {
197: unset($section->expireTime, $section->expireDelta, $section->expireIdentity,
198: $section->expireBrowser, $section->browserCheck, $section->authTime);
199: }
200:
201: return $this->sessionSection;
202: }
203:
204: }
205: