V1.1.3 安全性与稳定性的一些小改进

This commit is contained in:
2025-03-28 00:40:12 +08:00
parent b2078ad340
commit 0873fa1518
5 changed files with 46 additions and 47 deletions

7
.gitignore vendored
View File

@@ -1,4 +1,5 @@
data.db # DataBase
*.db
# environment # environment
.venv/ .venv/
@@ -9,5 +10,5 @@ data.db
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/
# C extensions # VsCodeCounter Data
*.so .VSCodeCounter/

View File

@@ -9,21 +9,14 @@ Description: Findreve 后台管理 admin
Copyright (c) 2018-2024 by 于小丘Yuerchu, All Rights Reserved. Copyright (c) 2018-2024 by 于小丘Yuerchu, All Rights Reserved.
''' '''
from nicegui import ui, app from nicegui import ui
from typing import Optional
from typing import Dict from typing import Dict
import traceback
import model import model
import asyncio
import qrcode import qrcode
import base64 import base64
from io import BytesIO from io import BytesIO
from PIL import Image
from fastapi import Request from fastapi import Request
import json
import requests
from tool import * from tool import *
from fastapi.responses import RedirectResponse
from datetime import datetime from datetime import datetime

View File

@@ -11,24 +11,23 @@ Copyright (c) 2018-2024 by 于小丘Yuerchu, All Rights Reserved.
from nicegui import ui, app from nicegui import ui, app
from typing import Optional from typing import Optional
import traceback
import asyncio
import model import model
import tool import tool
from fastapi.responses import RedirectResponse from fastapi.responses import RedirectResponse
from fastapi import Request
def create() -> Optional[RedirectResponse]: def create() -> Optional[RedirectResponse]:
@ui.page('/login') @ui.page('/login')
async def session(redirect_to: str = '/'): async def session(request: Request, redirect_to: str = "/"):
# 检测是否已登录 # 检测是否已登录
if app.storage.user.get('authenticated', False): if app.storage.user.get('authenticated', False):
ui.navigate.to(redirect_to) return ui.navigate.to(redirect_to)
ui.page_title('登录 Findreve') ui.page_title('登录 Findreve')
async def try_login() -> None: async def try_login() -> None:
app.storage.user.update({'authenticated': True}) app.storage.user.update({'authenticated': True})
# 跳转到用户上一页 # 跳转到用户上一页
ui.navigate.to(redirect_to) ui.navigate.to(app.storage.user.get('referrer_path', '/'))
async def login(): async def login():
if username.value == "" or password.value == "": if username.value == "" or password.value == "":

61
main.py
View File

@@ -9,12 +9,11 @@ Description: Findreve
Copyright (c) 2018-2024 by 于小丘Yuerchu, All Rights Reserved. Copyright (c) 2018-2024 by 于小丘Yuerchu, All Rights Reserved.
''' '''
from nicegui import app, ui, Client from nicegui import app, ui
from fastapi import Request from fastapi import Request
from starlette.middleware.base import BaseHTTPMiddleware from starlette.middleware.base import BaseHTTPMiddleware
from fastapi.responses import RedirectResponse, JSONResponse from fastapi.responses import RedirectResponse, JSONResponse
import hashlib import traceback
import inspect
import notfound import notfound
import main_page import main_page
@@ -39,39 +38,51 @@ AUTH_CONFIG = {
"session_expire": 3600 # 会话过期时间 "session_expire": 3600 # 会话过期时间
} }
# 登录验证中间件 Login verification middleware def is_restricted_route(path: str) -> bool:
"""判断路径是否为需要认证的受限路由"""
# NiceGUI 路由不受限制
if path.startswith('/_nicegui'):
return False
# 静态资源路径不受限制
if path.startswith('/static'):
return False
# 主题路径不受限制
if path.startswith('/theme'):
return False
# 后台路径始终受限
if path.startswith('/admin'):
return True
# 检查是否为受限的客户端页面路由
if path.startswith('/dash') or path.startswith('/user'):
return True
class AuthMiddleware(BaseHTTPMiddleware): class AuthMiddleware(BaseHTTPMiddleware):
# 异步处理每个请求
async def dispatch(self, request: Request, call_next): async def dispatch(self, request: Request, call_next):
try: try:
logging.info(f"访问路径: {request.url.path},"
f"认证状态: {app.storage.user.get('authenticated')}")
if not app.storage.user.get('authenticated', False): if not app.storage.user.get('authenticated', False):
# 如果请求的路径不是nicegui的静态文件并且不在unrestricted_page_routes中 path = request.url.path
if not request.url.path.startwith('/_nicegui') \
and request.url.path in AUTH_CONFIG["restricted_routes"]:
logging.warning(f"未认证用户尝试访问: {request.url.path}")
# 记录用户想访问的路径 Record the user's intended path
app.storage.user['referrer_path'] = request.url.path
# 重定向到登录页面 Redirect to the login page
return RedirectResponse(f'/login?redirect_to={request.url.path}')
# 否则,继续处理请求 Otherwise, continue processing the request
return await call_next(request)
if is_restricted_route(path):
logging.warning(f"未认证用户尝试访问: {path}")
return RedirectResponse(f'/login?redirect_to={path}')
return await call_next(request)
except Exception as e: except Exception as e:
# 记录错误日志 logging.error(f"服务器错误 Server error: {str(traceback.format_exc())}")
logging.error(f"认证中间件错误: {str(e)}") return JSONResponse(status_code=500, content={"detail": e})
# 返回适当的错误响应
return JSONResponse(
status_code=500,
content={"detail": "服务器内部错误"}
)
# 添加中间件 Add middleware # 添加中间件 Add middleware
app.add_middleware(AuthMiddleware) app.add_middleware(AuthMiddleware)
# 添加静态文件目录 # 添加静态文件目录
app.add_static_files(url_path='/static', local_directory='static') try:
app.add_static_files(url_path='/static', local_directory='static')
except RuntimeError:
logging.error('无法挂载静态目录')
# 启动函数 Startup function # 启动函数 Startup function
def startup(): def startup():

View File

@@ -14,12 +14,7 @@ import random
import hashlib import hashlib
import binascii import binascii
import logging import logging
import qrcode from datetime import datetime, timezone
from typing import Optional
from io import BytesIO
from pathlib import Path
import base64
from datetime import datetime, timezone, timedelta
import os import os
def format_phone(phone: str, groups: list = None, separator: str = " ", private: bool = False) -> str: def format_phone(phone: str, groups: list = None, separator: str = " ", private: bool = False) -> str: