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