1 <?php
2
3 4 5 6 7 8
9 class rex_backend_login extends rex_login
10 {
11 const SYSTEM_ID = 'backend_login';
12 const LOGIN_TRIES_1 = 3;
13 const RELOGIN_DELAY_1 = 5;
14 const LOGIN_TRIES_2 = 50;
15 const RELOGIN_DELAY_2 = 3600;
16
17 private $tableName;
18 private $stayLoggedIn;
19
20 public function __construct()
21 {
22 parent::__construct();
23
24 $tableName = rex::getTablePrefix() . 'user';
25 $this->setSqlDb(1);
26 $this->setSystemId(self::SYSTEM_ID);
27 $this->setSessionDuration(rex::getProperty('session_duration'));
28 $qry = 'SELECT * FROM ' . $tableName;
29 $this->setUserQuery($qry . ' WHERE id = :id AND status = 1');
30 $this->setImpersonateQuery($qry . ' WHERE id = :id');
31
32 $this->setLoginQuery($qry . ' WHERE
33 status = 1
34 AND login = :login
35 AND (login_tries < ' . self::LOGIN_TRIES_1 . '
36 OR login_tries < ' . self::LOGIN_TRIES_2 . ' AND lasttrydate < "' . rex_sql::datetime(time() - self::RELOGIN_DELAY_1) . '"
37 OR lasttrydate < "' . rex_sql::datetime(time() - self::RELOGIN_DELAY_2) . '"
38 )'
39 );
40 $this->tableName = $tableName;
41 }
42
43 public function setStayLoggedIn($stayLoggedIn = false)
44 {
45 $this->stayLoggedIn = $stayLoggedIn;
46 }
47
48 public function checkLogin()
49 {
50 $sql = rex_sql::factory();
51 $userId = $this->getSessionVar('UID');
52 $cookiename = self::getStayLoggedInCookieName();
53
54 if ($cookiekey = rex_cookie($cookiename, 'string')) {
55 if (!$userId) {
56 $sql->setQuery('SELECT id FROM ' . rex::getTable('user') . ' WHERE cookiekey = ? LIMIT 1', [$cookiekey]);
57 if ($sql->getRows() == 1) {
58 $this->setSessionVar('UID', $sql->getValue('id'));
59 rex_response::sendCookie($cookiename, $cookiekey, ['expires' => strtotime('+1 year'), 'samesite' => 'strict']);
60 } else {
61 self::deleteStayLoggedInCookie();
62 }
63 }
64 $this->setSessionVar('STAMP', time());
65 }
66
67 $check = parent::checkLogin();
68
69 if ($check) {
70
71 if ($this->userLogin != '' || !$userId) {
72 self::regenerateSessionId();
73 $params = [];
74 $add = '';
75 if ($this->stayLoggedIn || $cookiekey) {
76 $cookiekey = sha1($this->systemId . time() . $this->userLogin);
77 $add = 'cookiekey = ?, ';
78 $params[] = $cookiekey;
79 rex_response::sendCookie($cookiename, $cookiekey, ['expires' => strtotime('+1 year'), 'samesite' => 'strict']);
80 }
81 if (self::passwordNeedsRehash($this->user->getValue('password'))) {
82 $add .= 'password = ?, ';
83 $params[] = self::passwordHash($this->userPassword, true);
84 }
85 array_push($params, rex_sql::datetime(), rex_sql::datetime(), session_id(), $this->userLogin);
86 $sql->setQuery('UPDATE ' . $this->tableName . ' SET ' . $add . 'login_tries=0, lasttrydate=?, lastlogin=?, session_id=? WHERE login=? LIMIT 1', $params);
87 }
88
89 $this->user = new rex_user($this->user);
90
91 if ($this->impersonator instanceof rex_sql) {
92 $this->impersonator = new rex_user($this->impersonator);
93 }
94 } else {
95
96 if ($this->userLogin != '') {
97 $sql->setQuery('SELECT login_tries FROM ' . $this->tableName . ' WHERE login=? LIMIT 1', [$this->userLogin]);
98 if ($sql->getRows() > 0) {
99 $login_tries = $sql->getValue('login_tries');
100 $sql->setQuery('UPDATE ' . $this->tableName . ' SET login_tries=login_tries+1,session_id="",cookiekey="",lasttrydate=? WHERE login=? LIMIT 1', [rex_sql::datetime(), $this->userLogin]);
101 if ($login_tries >= self::LOGIN_TRIES_1 - 1) {
102 $time = $login_tries < self::LOGIN_TRIES_2 ? self::RELOGIN_DELAY_1 : self::RELOGIN_DELAY_2;
103 $hours = floor($time / 3600);
104 $mins = floor(($time - ($hours * 3600)) / 60);
105 $secs = $time % 60;
106 $formatted = ($hours ? $hours . 'h ' : '') . ($hours || $mins ? $mins . 'min ' : '') . $secs . 's';
107 $this->message .= ' ' . rex_i18n::rawMsg('login_wait', '<strong data-time="' . $time . '">' . $formatted . '</strong>');
108 }
109 }
110 }
111 }
112
113 if ($this->isLoggedOut() && $userId != '') {
114 $sql->setQuery('UPDATE ' . $this->tableName . ' SET session_id="", cookiekey="" WHERE id=? LIMIT 1', [$userId]);
115 self::deleteStayLoggedInCookie();
116 }
117
118 return $check;
119 }
120
121 public static function deleteSession()
122 {
123 self::startSession();
124
125 unset($_SESSION[static::getSessionNamespace()][self::SYSTEM_ID]);
126 self::deleteStayLoggedInCookie();
127
128 rex_csrf_token::removeAll();
129 }
130
131 private static function deleteStayLoggedInCookie()
132 {
133 rex_response::sendCookie(self::getStayLoggedInCookieName(), '');
134 }
135
136 private static function getStayLoggedInCookieName()
137 {
138 return 'rex_user_' . sha1(rex::getProperty('instname'));
139 }
140
141 public static function hasSession()
142 {
143
144 if (!isset($_COOKIE[session_name()])) {
145 return false;
146 }
147 self::startSession();
148
149 $sessionNs = static::getSessionNamespace();
150 return isset($_SESSION[$sessionNs][self::SYSTEM_ID]['UID']) && $_SESSION[$sessionNs][self::SYSTEM_ID]['UID'] > 0;
151 }
152
153 154 155 156 157 158 159 160
161 public static function createUser()
162 {
163 if (!self::hasSession()) {
164 return null;
165 }
166 if ($user = rex::getUser()) {
167 return $user;
168 }
169
170 $login = new self();
171 rex::setProperty('login', $login);
172 if ($login->checkLogin()) {
173 $user = $login->getUser();
174 rex::setProperty('user', $user);
175 return $user;
176 }
177 return null;
178 }
179
180 181 182 183 184
185 protected static function getSessionNamespace()
186 {
187 return rex::getProperty('instname'). '_backend';
188 }
189 }
190