浏览代码

a redirect was made to the requested page after authorization

root 9 月之前
父节点
当前提交
8e3e670d1a
共有 4 个文件被更改,包括 46 次插入28 次删除
  1. 1 21
      html/inc/auth.php
  2. 16 6
      html/inc/auth.utils.php
  3. 5 0
      html/inc/consts.php
  4. 24 1
      html/login.php

+ 1 - 21
html/inc/auth.php

@@ -3,26 +3,6 @@ require_once ($_SERVER['DOCUMENT_ROOT']."/inc/auth.utils.php");
 
 login($db_link);
 
-if (!empty($_GET['redirect'])) {
-    // Очищаем и проверяем URL
-    $redirect = trim($_GET['redirect']);
-    // Удаляем все слеши в начале, чтобы избежать дублирования
-    $redirect = ltrim($redirect, '/');
-    // Проверяем, что URL не ведет на другой домен и не содержит опасных символов
-    if (preg_match('/^[a-zA-Z0-9\-_\/\.]+$/', $redirect) && 
-        strpos($redirect, '..') === false && 
-        strpos($redirect, '//') === false) {
-        // Проверяем, что текущий URL не совпадает с целевым
-        $currentPath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
-        $currentPath = ltrim($currentPath, '/');
-        if ($currentPath !== $redirect) {
-            header('Location: /' . $redirect);
-            exit;
-        }
-    }
-    // Если проверки не прошли - игнорируем
-}
-
 $start_time = microtime();
 $start_array = explode(" ",$start_time);
 $start_time = $start_array[1] + $start_array[0];
@@ -40,7 +20,7 @@ if (!empty($_POST['id'])) { $id = $_POST["id"]; }
 if (!empty($id) and !empty($page_url)) { $page_url = $page_url.'?id='.$id; }
 
 if (empty($page_url)) {
-    header("Location: /admin/index.php");
+    header("Location: ".DEFAULT_PAGE);
     exit;
     }
 

+ 16 - 6
html/inc/auth.utils.php

@@ -88,6 +88,13 @@ function sess_gc($maxLifetime) {
 
 function login($db) {
 
+    $current_url = urlencode($_SERVER['REQUEST_URI']);
+    $redirect_url = NULL;
+
+    if ($_SERVER['REQUEST_URI'] != LOGIN_PAGE && $_SERVER['REQUEST_URI'] != LOGOUT_PAGE) {
+        $redirect_url = $current_url;
+        }
+
     // 1. Проверка активной сессии
     if (!empty($_SESSION['user_id']) && validate_session($db)) {
         // Дополнительная валидация сессии
@@ -96,7 +103,7 @@ function login($db) {
             return true;
         }
         // Несоответствие параметров - разрушаем сессию
-        logout($db);
+        logout($db,FALSE,$redirect_url);
     }
 
     // 2. Проверка API-авторизации (для API-запросов)
@@ -107,7 +114,7 @@ function login($db) {
     // 4. Проверка логина/пароля из POST-данных (обычная форма входа)
     if (!empty($_POST['login']) && !empty($_POST['password'])) {
         if (authenticate_by_credentials($db, $_POST['login'], $_POST['password'])) {
-            LOG_INFO($db, "Logged in customer id: ".$_SESSION['user_id']." name: ".$_SESSION['login']." from ".$_SESSION['ip']." with acl: ".$_SESSION['acl']);
+            LOG_INFO($db, "Logged in customer id: ".$_SESSION['user_id']." name: ".$_SESSION['login']." from ".$_SESSION['ip']." with acl: ".$_SESSION['acl']." url: ".$redirect_url);
             return true;
         }
         // Неудачная попытка входа
@@ -115,7 +122,7 @@ function login($db) {
     }
 
     // 5. Если ни один метод не сработал - требовать авторизацию
-    logout($db);
+    logout($db,FALSE,$redirect_url);
     exit;
 }
 
@@ -277,7 +284,7 @@ function IsSilentAuthenticated($db) {
 }
 
 // Выход из системы (полная версия)
-function logout($db, $silent = FALSE) {
+function logout($db, $silent = FALSE, $redirect_url = DEFAULT_PAGE) {
     if (session_status() === PHP_SESSION_ACTIVE) {
         LOG_INFO($db, "Logout customer id: ".$_SESSION['user_id']." name: ".$_SESSION['login']." from ".$_SESSION['ip']." with acl: ".$_SESSION['acl']);
         // Деактивация сессии в БД
@@ -296,8 +303,11 @@ function logout($db, $silent = FALSE) {
         }
     }
     if (!$silent) {
-        header('Location: /login.php');
-        //?redirect=' . urlencode($_SERVER['REQUEST_URI']));
+        if ($redirect_url == DEFAULT_PAGE) {
+            header('Location: '.LOGIN_PAGE);
+            } else {
+            header('Location: '.LOGIN_PAGE.'?redirect_url='.$redirect_url);
+            }
         }
 }
 

+ 5 - 0
html/inc/consts.php

@@ -211,4 +211,9 @@ define('MYSQL_FIELD_STRING', array(252,253,254));
 //lock device by snmp access
 define('SNMP_LOCK_TIMEOUT',30);
 
+//login pages
+define('DEFAULT_PAGE','/admin/index.php');
+define('LOGIN_PAGE','/login.php');
+define('LOGOUT_PAGE','/logout.php');
+
 ?>

+ 24 - 1
html/login.php

@@ -5,6 +5,25 @@ require_once ($_SERVER['DOCUMENT_ROOT']."/inc/languages/" . HTML_LANG . ".php");
 
 $error = '';
 
+function getSafeRedirectUrl(string $default = '/'): string {
+    $url = filter_input(INPUT_GET, 'redirect_url', FILTER_SANITIZE_URL) 
+        ?? filter_input(INPUT_POST, 'redirect_url', FILTER_SANITIZE_URL) 
+        ?? $default;
+
+    $decodedUrl = urldecode($url);
+    // Проверяем:
+    // 1. URL начинается с `/` (но не `//` или `http://`)
+    // 2. Содержит только разрешённые символы (a-z, 0-9, -, _, /, ?, =, &, ., ~)
+    if (!preg_match('/^\/(?!\/)[a-z0-9\-_\/?=&.~]*$/i', $decodedUrl)) {
+        return $default;
+    }
+
+    return $url;
+}
+
+// Использование
+$redirect_url = getSafeRedirectUrl(DEFAULT_PAGE);
+
 if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['submit'])) {
 
     $login = trim($_POST['login']);
@@ -21,7 +40,10 @@ if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['submit'])) {
 	}
 
     if (empty($error)) {
-	if (login($db_link)) { header("Location: /admin/index.php"); }
+	if (login($db_link)) { 
+            $redirect_url = urldecode($redirect_url);
+            header("Location: $redirect_url");
+            }
 	}
 
     }
@@ -48,6 +70,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['submit'])) {
 		    <i class="fas fa-lock"></i>
 		</label>
 		<input type="password" name="password" placeholder="<?php echo WEB_msg_password; ?>" id="password" required>
+                <input type="hidden" name="redirect_url" value="<?php print htmlspecialchars($redirect_url); ?>">
 		<input type="submit" name="submit" value="<?php echo WEB_btn_login; ?>">
 	    </form>
 	</div>