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