Files
mirror_server/api/admin.py
T
HYC Fixer 2a899c411e P0-C: 安全修复
- 会话文件移出 web 根(data/ 目录),auth_secret 启动自动生成并持久化(0600)
- cookie 签名改 HMAC-SHA256 + compare_digest;会话表加锁 + 原子写
- serve_path 增加敏感文件黑名单(纵深防御)
- PyPI: 移除 ?url= 任意 URL 回退(SSRF),限制 scheme,缓存键防路径穿越
- v2 文件元数据/版本/缩略图端点全部加 is_safe_path;缩略图尺寸与像素上限
- api-docs/generate 限写 docs 目录;user/password 强制旧密码;GET /api/v2/config 脱敏
- 目录列表/错误页 HTML 转义(防存储型 XSS);Content-Disposition 文件名清洗
- 信号处理改优雅退出(移除 os._exit);启动时默认凭据安全警告
2026-08-30 12:20:17 +08:00

119 lines
4.0 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
管理员API处理器
提供认证相关API(无 keys 管理)
"""
import json
import time
from core.api_auth import APIAuthManager, require_auth
class AdminAPI:
"""管理员API处理器"""
def __init__(self, config: dict):
self.config = config
self.auth_manager = APIAuthManager(config)
def handle_request(self, handler, method, path, query_params):
"""处理管理员API请求"""
# 解析路径
parts = path.strip('/').split('/')
# 根路径 - 列出API
if len(parts) == 0 or parts[0] == '':
self._api_overview(handler)
return
action = parts[0]
if action == 'auth':
self._handle_auth(handler, method, query_params)
elif action == 'sessions':
self._handle_sessions(handler, method, parts[1:] if len(parts) > 1 else [])
elif action == 'stats':
self._handle_stats(handler)
else:
handler.send_json_response({
"error": f"Unknown admin action: {action}",
"available_actions": ["auth", "sessions", "stats"]
}, 404)
def _api_overview(self, handler):
"""API概览"""
handler.send_json_response({
"name": "HYC Admin API",
"version": "1.0",
"description": "管理员认证API",
"endpoints": {
"GET /api/v2/admin/sessions": "列出活跃会话",
"DELETE /api/v2/admin/sessions/{session_id}": "销毁会话",
"POST /api/v2/admin/auth/verify": "验证认证状态",
"GET /api/v2/admin/stats": "获取认证统计"
},
"authentication": {
"methods": [
"Authorization: Bearer <token>",
"X-API-Key: <token>",
"Cookie: hyc_auth=<session>",
"?key=<token>"
]
}
})
def _handle_auth(self, handler, method, query_params):
"""处理认证相关"""
# POST /api/v2/admin/auth/verify - 验证当前认证状态
if method == 'POST':
auth_result = handler.auth_result if hasattr(handler, 'auth_result') else {}
if auth_result.get('authenticated'):
handler.send_json_response({
"authenticated": True,
"level": auth_result.get('level'),
"key_id": auth_result.get('key_id'),
"name": auth_result.get('name'),
"permissions": auth_result.get('permissions', [])
})
else:
handler.send_json_response({
"authenticated": False
}, 401)
else:
handler.send_json_response({"error": "Invalid method"}, 405)
def _handle_sessions(self, handler, method, parts):
"""处理会话管理"""
if method == 'GET':
# 列出活跃会话(auth_manager 内部加锁遍历)
sessions = self.auth_manager.list_sessions()
handler.send_json_response({
"sessions": sessions,
"count": len(sessions)
})
elif method == 'DELETE' and len(parts) >= 1 and parts[0]:
session_id = parts[0]
success = self.auth_manager.destroy_session(session_id)
if success:
handler.send_json_response({
"success": True,
"message": f"Session {session_id} destroyed"
})
else:
handler.send_json_response({"error": "Session not found"}, 404)
else:
handler.send_json_response({"error": "Invalid request"}, 400)
def _handle_stats(self, handler):
"""获取认证统计"""
stats = self.auth_manager.get_stats()
handler.send_json_response(stats)