前幾天已經完成事件解析、欄位標準化以及 Severity 的基本分類。不過,隨著 Security Event 數量增加,如果只能從 Dashboard 的表格中逐筆查看資料,實際使用上會相當不方便。
因此今天開始加入事件搜尋功能,希望可以透過 Event Type、IP、Protocol 或 Signature 等資訊,快速找到需要進一步分析的事件。
今天在 FastAPI 中新增:
GET /events/search
並使用 Query Parameter 接收搜尋關鍵字。例如:
/events/search?q=Network
Backend 收到關鍵字後,會透過 SQLite 搜尋欄位:
event_type
src_ip
dest_ip
protocol
signature
實際搜尋 Network 後,可以成功找到先前建立的 Network Scan 測試事件。
修改 main.py
重新啟動 FastAPI
於 FastAPI 新增 Security Event Search API
搜尋 Network
再測 IP 搜尋同樣找到Network Scan,因為我們的 SQL 不只搜尋 event_type,還搜尋src_ip、dest_ip、protocol、signature
Login 找到 Login Attempt
今天在 SQLite 搜尋時,沒有直接將使用者輸入拼接到 SQL 指令,而是使用參數化查詢:
rows = conn.execute("""
SELECT * FROM events
WHERE event_type LIKE ?
OR src_ip LIKE ?
OR dest_ip LIKE ?
OR protocol LIKE ?
OR signature LIKE ?
""", (
keyword,
keyword,
keyword,
keyword,
keyword
)).fetchall()
除了程式比較容易維護之外,也可以避免直接將外部輸入組合進 SQL 指令,降低 SQL Injection 等不必要的風險。
完成 Backend Search API 後,我進一步在 React Dashboard 加入搜尋框。
當使用者輸入:Network
React 會呼叫:
GET /events/search?q=Network
FastAPI 再從 SQLite 搜尋符合條件的 Event,最後將結果回傳給 React。
整體流程為:
使用者輸入 Network
↓
React Search Box
↓
GET /events/search?q=Network
↓
FastAPI
↓
SQLite
↓
找到 Network Scan
↓
React 顯示搜尋結果
在App.jsx新增 search state
const [events, setEvents] = useState([]);
// 加入
const [search, setSearch] = useState("");
建立搜尋函式
在useEffect後面加入:
const searchEvents = () => {
if (search.trim() === "") {
fetch("http://127.0.0.1:8000/events")
.then((response) => response.json())
.then((data) => setEvents(data));
return;
}
fetch(
`http://127.0.0.1:8000/events/search?q=${encodeURIComponent(search)}`
)
.then((response) => response.json())
.then((data) => {
setEvents(data.results);
})
.catch((error) => {
console.error("Search error:", error);
});
};
加入搜尋框
<h2>Recent Security Events</h2>
// 加入搜尋框
<div className="search-box">
<input
type="text"
placeholder="Search event, IP, protocol..."
value={search}
onChange={(e) => setSearch(e.target.value)}
/>
<button onClick={searchEvents}>
Search
</button>
</div>
在nano src/App.css加 CSS
測試 Dashboard 搜尋
npm run dev -- --host 0.0.0.0
