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