import pandas as pd import os from datetime import datetime import joblib # 確保有安裝此套件 # --- 全域變數與模型載入 --- global system_weights system_weights = {"ow": 0, "gw": 0, "tw": 0} # 嘗試載入您的 HDBSCAN 模型 HDBSCAN_MODEL = None try: if os.path.exists('hdbscan_model.pkl'): HDBSCAN_MODEL = joblib.load('hdbscan_model.pkl') print("✅ HDBSCAN 模型載入成功") except Exception as e: print(f"❌ 模型載入失敗: {e}") # --- 新增:將系統行為映射至 Web Log 特徵 --- def map_to_web_log_features(action, status_label): """ 將內部 action 轉換為訓練資料中的 Method, Path, Status 數字 """ method = "GET" path = "/usr/student" status_code = 200 # 映射邏輯 (根據您的訓練資料截圖進行模擬) if action == "login_attempt": method = "POST" path = "/usr/login" elif "admin" in action or "manage" in action: path = "/usr/admin" elif action == "malicious_sql_injection": method = "DELETE" path = "/usr/admin/developer" # 根據狀態標籤給予初始代碼 if "failed" in status_label: status_code = 401 elif "異常" in status_label: status_code = 403 return method, path, status_code # --- 修改後的 check_anomaly --- def check_anomaly(ip, account, action, log_time): # 如果是登入或登出,直接放行 (200) if action in ["login_attempt", "logout"]: return "success (200)" try: ow = float(system_weights.get("ow", 0)) gw = float(system_weights.get("gw", 0)) tw = float(system_weights.get("tw", 0)) # 1. 地理位置權重攔截 from logger_service import get_geo_level # 假設此函式存在於同檔案 geo_level = get_geo_level(ip) if gw == 100 and geo_level > 0: return "⚠️異常_地理位置受限 (100%絕對鎖定: 僅限校內專網存取) (403)" elif gw >= 90 and geo_level > 1: return "⚠️異常_地理位置受限 (高敏感防護: 僅限校園網路與宿舍) (403)" # 2. 頻率檢查 # (此處保留您原有的 recent_clicks 計算邏輯...) # if (recent_clicks + 1) > max_allowed_clicks: # return f"⚠️異常_單一操作頻率過高 (403)" # 3. HDBSCAN 模型檢測 if HDBSCAN_MODEL: # 轉換特徵 method, path, base_code = map_to_web_log_features(action, "success") # ⚠️ 注意:這裡需要接入您當初訓練時的「特徵工程」轉換代碼 (例如 LabelEncoder 或 Scaler) # 範例結構: # features = preprocess_logic(ip, log_time, method, path, base_code) # result = HDBSCAN_MODEL.fit_predict(features) # if result[-1] == -1: return "⚠️異常_作息或行為不符 (403)" pass return "success (200)" except Exception as e: return f"⚠️系統錯誤: {str(e)} (500)"