fix: 审核引擎优化 + 执行结果结构化展示

后端审核规则修复:
- Redis SEC-001: SET/DEL等常规命令不再误报AUTH要求,改为仅对管理级命令WARNING
- Redis SEC-003: 降级为INFO,排除已由CMD-001拦截的FLUSHDB/FLUSHALL
- Redis key提取: 排除CONFIG/ACL等管理命令,不再把子命令参数误认为key名
- MySQL SEC-006: 新增GRANT ALL/REVOKE ALL全局权限拦截
- MySQL SEC-007: 新增LOAD DATA/LOAD XML拦截
- MySQL SEC-008: 新增SLEEP()/BENCHMARK()时间盲注拦截
- MySQL SEC-009: 新增INTO OUTFILE/DUMPFILE文件写入拦截

前端执行结果结构化:
- TicketDetailPage执行结果从原始JSON改为结构化展示
- 解析JSON展示: 状态徽章+影响行数+耗时+验证状态
- Errors/Warnings逐条渲染: 红色错误框+黄色警告框+具体消息
- 删除废弃的executeStats/renderExecuteStats

其他: 审核规则6分组/慢查询移除/查询数据重命名/AuditLogs修复
测试: 1040 passed, TSC零错误
This commit is contained in:
logan committed 2026-05-24 01:31:33 +08:00
1 parent 9f56e866f2
commit 4ac2528f8e
19 files changed
+1202 -325

No files matched your search

+57
View File
@@ -5,6 +5,7 @@ Replaces mock aiomysql calls with actual driver connections.
"""
import asyncio
import time
import asyncio
import sqlite3
from typing import Optional, List, Dict, Any, Tuple
@@ -61,12 +62,68 @@ class DBConnector:
return await DBConnector._test_postgres(instance, start)
elif instance.db_type == "sqlite":
return await DBConnector._test_sqlite(instance, start)
elif instance.db_type == "redis":
return await DBConnector._test_redis(instance, start)
elif instance.db_type == "mongodb":
return await DBConnector._test_mongodb(instance, start)
else:
return ConnectionResult(False, f"暂不支持 {instance.db_type} 类型数据源")
except Exception as e:
elapsed = int((time.time() - start) * 1000)
return ConnectionResult(False, f"连接失败: {str(e)}", latency_ms=elapsed)
@staticmethod
async def _test_redis(instance: 'Instance', start: float) -> ConnectionResult:
"""Test Redis connectivity using synchronous redis client in thread."""
try:
import redis as redis_lib
def _connect():
client = redis_lib.Redis(
host=instance.host,
port=instance.port,
password=instance.password if instance.password and instance.password != "default" else None,
db=0,
socket_connect_timeout=5,
socket_timeout=5,
)
info = client.info("server")
version = info.get("redis_version", "unknown")
client.close()
return version
version = await asyncio.to_thread(_connect)
elapsed = int((time.time() - start) * 1000)
return ConnectionResult(True, f"Redis {version} 连接成功", version=version, latency_ms=elapsed)
except Exception as e:
elapsed = int((time.time() - start) * 1000)
return ConnectionResult(False, f"Redis 连接失败: {str(e)}", latency_ms=elapsed)
@staticmethod
async def _test_mongodb(instance: 'Instance', start: float) -> ConnectionResult:
"""Test MongoDB connectivity using pymongo in thread."""
try:
from pymongo import MongoClient
def _connect():
if instance.username and instance.username != "default":
uri = f"mongodb://{instance.username}:{instance.password}@{instance.host}:{instance.port}/"
else:
uri = f"mongodb://{instance.host}:{instance.port}/"
client = MongoClient(uri, serverSelectionTimeoutMS=5000, connectTimeoutMS=5000)
info = client.server_info()
version = info.get("version", "unknown")
client.close()
return version
version = await asyncio.to_thread(_connect)
elapsed = int((time.time() - start) * 1000)
return ConnectionResult(True, f"MongoDB {version} 连接成功", version=version, latency_ms=elapsed)
except Exception as e:
elapsed = int((time.time() - start) * 1000)
return ConnectionResult(False, f"MongoDB 连接失败: {str(e)}", latency_ms=elapsed)
@staticmethod
async def execute_query(
instance: Instance, database: Optional[str], sql: str, user_id: int