From 8d1b1379e93e1d6847eb24266a461322ebb02177 Mon Sep 17 00:00:00 2001 From: 3 Date: Fri, 30 May 2025 13:47:28 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9F=BA=E7=A1=80api=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=8F=AF=E8=BF=9B=E8=A1=8C,=E5=8F=AF=E6=89=AB=E6=8F=8F?= =?UTF-8?q?=E7=BD=91=E7=BB=9C=E4=BA=A4=E6=8D=A2=E6=9C=BA=EF=BC=8C=E9=9C=80?= =?UTF-8?q?=E7=94=A8=E8=AE=BE=E5=A4=87=E8=BF=9B=E4=B8=80=E6=AD=A5=E8=B0=83?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/.gitignore | 14 ++++-- src/backend/Dockerfile | 19 +++++--- src/backend/app/__init__.py | 2 +- src/backend/app/api/endpoints.py | 26 +++++++++-- src/backend/app/services/network_scanner.py | 49 +++++++++++++++++++++ src/backend/requirements.txt | 3 +- 6 files changed, 98 insertions(+), 15 deletions(-) create mode 100644 src/backend/app/services/network_scanner.py diff --git a/src/backend/.gitignore b/src/backend/.gitignore index f03fe47..2e78f75 100644 --- a/src/backend/.gitignore +++ b/src/backend/.gitignore @@ -1,7 +1,10 @@ +# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class *.so + +# Python packaging .Python build/ develop-eggs/ @@ -23,6 +26,8 @@ MANIFEST # IDE .idea/ .vscode/ +*.swp +*.swo # Environment .env @@ -35,7 +40,10 @@ venv.bak/ # Logs *.log +*.log.* +logs/ -# 忽略.env文件 -.env -*.secret \ No newline at end of file +# Secrets +*.secret +*.key +*.pem \ No newline at end of file diff --git a/src/backend/Dockerfile b/src/backend/Dockerfile index e8df141..2da8f24 100644 --- a/src/backend/Dockerfile +++ b/src/backend/Dockerfile @@ -2,16 +2,21 @@ FROM python:3.13-slim WORKDIR /app +# 1. 先复制依赖文件并安装 COPY ./requirements.txt /app/requirements.txt - RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt +# 2. 复制项目代码(排除 .env 和缓存文件) COPY . /app -ENV PYTHONPATH=/app -ENV PORT=8000 -ENV HOST=0.0.0.0 -.env -*.secret +# 3. 环境变量配置 +ENV PYTHONPATH=/app \ + PORT=8000 \ + HOST=0.0.0.0 -CMD ["uvicorn", "run:app", "--host", "0.0.0.0", "--port", "8000", "--reload"] \ No newline at end of file +# 4. 安全设置 +RUN find /app -name "*.pyc" -delete && \ + find /app -name "__pycache__" -exec rm -rf {} + + +# 5. 启动命令(修正路径) +CMD ["uvicorn", "src.backend.app:app", "--host", "0.0.0.0", "--port", "8000"] \ No newline at end of file diff --git a/src/backend/app/__init__.py b/src/backend/app/__init__.py index a187fdf..3963a5e 100644 --- a/src/backend/app/__init__.py +++ b/src/backend/app/__init__.py @@ -4,7 +4,7 @@ from src.backend.app.utils.logger import setup_logging from src.backend.config import settings app = FastAPI() -app.include_router(router) +app.include_router(router,prefix="/api") def create_app() -> FastAPI: # 设置日志 diff --git a/src/backend/app/api/endpoints.py b/src/backend/app/api/endpoints.py index b8fdbfe..8aa16bc 100644 --- a/src/backend/app/api/endpoints.py +++ b/src/backend/app/api/endpoints.py @@ -2,16 +2,36 @@ from fastapi import APIRouter, Depends, HTTPException from typing import Any from pydantic import BaseModel -from src.backend.app.services.ai_services import AIService -from src.backend.app.api.network_config import SwitchConfigurator -from src.backend.config import settings +from ...app.services.ai_services import AIService +from ...app.api.network_config import SwitchConfigurator +from ...config import settings +from ..services.network_scanner import NetworkScanner router = APIRouter(prefix="/api", tags=["API"]) +scanner = NetworkScanner() @router.get("/test") async def test_endpoint(): return {"message": "Hello World"} +@router.get("/scan_network", summary="扫描网络中的交换机") +async def scan_network(subnet: str = "192.168.1.0/24"): + try: + devices = scanner.scan_subnet(subnet) + return { + "success": True, + "devices": devices, + "count": len(devices) + } + except Exception as e: + raise HTTPException(500, f"扫描失败: {str(e)}") + +@router.get("/list_devices", summary="列出已发现的交换机") +async def list_devices(): + return { + "devices": scanner.load_cached_devices() + } + class CommandRequest(BaseModel): command: str diff --git a/src/backend/app/services/network_scanner.py b/src/backend/app/services/network_scanner.py new file mode 100644 index 0000000..bf514c5 --- /dev/null +++ b/src/backend/app/services/network_scanner.py @@ -0,0 +1,49 @@ +import nmap +import json +from pathlib import Path +from typing import List, Dict +from ..utils.logger import logger + + +class NetworkScanner: + def __init__(self, cache_path: str = "switch_devices.json"): + self.cache_path = Path(cache_path) + self.nm = nmap.PortScanner() + + def scan_subnet(self, subnet: str = "192.168.1.0/24") -> List[Dict]: + """扫描指定子网的交换机设备""" + logger.info(f"Scanning subnet: {subnet}") + + # 扫描开放22(SSH)或23(Telnet)端口的设备 + self.nm.scan( + hosts=subnet, + arguments="-p 22,23 --open -T4" + ) + + devices = [] + for host in self.nm.all_hosts(): + if self.nm[host].state() == "up": + device = { + "ip": host, + "ports": list(self.nm[host]["tcp"].keys()), + "mac": self.nm[host].get("addresses", {}).get("mac", "unknown") + } + devices.append(device) + logger.debug(f"Found device: {device}") + + self._save_to_cache(devices) + return devices + + def _save_to_cache(self, devices: List[Dict]): + """保存扫描结果到本地文件""" + with open(self.cache_path, "w") as f: + json.dump(devices, f, indent=2) + logger.info(f"Saved {len(devices)} devices to cache") + + def load_cached_devices(self) -> List[Dict]: + """从缓存加载设备列表""" + if not self.cache_path.exists(): + return [] + + with open(self.cache_path) as f: + return json.load(f) \ No newline at end of file diff --git a/src/backend/requirements.txt b/src/backend/requirements.txt index 7f2f48d..7ce79b3 100644 --- a/src/backend/requirements.txt +++ b/src/backend/requirements.txt @@ -4,4 +4,5 @@ python-dotenv==1.0.0 requests==2.28.2 paramiko==3.1.0 pydantic==1.10.7 -loguru==0.7.0 \ No newline at end of file +loguru==0.7.0 +python-nmap==0.7.1 \ No newline at end of file