features: 添加nginx代理支持

This commit is contained in:
luoja 2025-03-17 10:35:07 +08:00
parent f6bbdf5bbe
commit 3f8c6ad096
7 changed files with 80 additions and 19 deletions

40
src/common/constant.py Normal file
View File

@ -0,0 +1,40 @@
class HttpStatusConstant:
"""
返回状态码
SUCCESS: 操作成功
CREATED: 对象创建成功
ACCEPTED: 请求已经被接受
NO_CONTENT: 操作已经执行成功但是没有返回数据
MOVED_PERM: 资源已被移除
SEE_OTHER: 重定向
NOT_MODIFIED: 资源没有被修改
BAD_REQUEST: 参数列表错误缺少格式不匹配
UNAUTHORIZED: 未授权
FORBIDDEN: 访问受限授权过期
NOT_FOUND: 资源服务未找到
BAD_METHOD: 不允许的http方法
CONFLICT: 资源冲突或者资源被锁
UNSUPPORTED_TYPE: 不支持的数据媒体类型
ERROR: 系统内部错误
NOT_IMPLEMENTED: 接口未实现
WARN: 系统警告消息
"""
SUCCESS = 200
CREATED = 201
ACCEPTED = 202
NO_CONTENT = 204
MOVED_PERM = 301
SEE_OTHER = 303
NOT_MODIFIED = 304
BAD_REQUEST = 400
UNAUTHORIZED = 401
FORBIDDEN = 403
NOT_FOUND = 404
BAD_METHOD = 405
CONFLICT = 409
UNSUPPORTED_TYPE = 415
ERROR = 500
NOT_IMPLEMENTED = 501
WARN = 601

View File

@ -2,21 +2,24 @@ from flask import request
from user_agents import parse
from typing import Literal, Optional
from dataclasses import dataclass
from config.dashgo_conf import ProxyConf
browser_type = Literal['Chrome', 'Firefox', 'Safari', 'IE', 'Edge', 'Opera', 'Other']
browser_type = Literal['chrome', 'firefox', 'safari', 'ie']
@dataclass
class BrowserInfo:
url: str
type: browser_type
version: Optional[int]
ip: str
request_addr: str
def get_browser_info() -> BrowserInfo:
request_addr = request.remote_addr
# 取代理链的第一个IP为用户IP
request_addr = request.headers.get('X-Forwarded-For').split(',')[0] if ProxyConf.NGINX_PROXY else request.remote_addr
user_string = str(request.user_agent)
user_agent = parse(user_string)
bw: browser_type = user_agent.browser.family
version: Optional[int] = user_agent.browser.version[0] if user_agent.browser.version else None
return BrowserInfo(type=bw.lower(), version=version, ip=request_addr)
return BrowserInfo(type=bw.lower(), version=version, request_addr=request_addr, url=request.url)

View File

@ -20,11 +20,11 @@ VERIFY_CODE_CHAR_NUM = 4
JWT_EXPIRED_FORCE_LOGOUT = False
[LogConf]
LOG_LEVEL = DEBUG
LOG_LEVEL = INFO
# open console log?
HANDLER_CONSOLE = True
HANDLER_CONSOLE = False
# open log file?
HANDLER_LOG_FILE = False
HANDLER_LOG_FILE = True
LOG_FILE_PATH = ./DashGo.log
MAX_MB_PER_LOG_FILE = 50
MAX_COUNT_LOG_FILE = 3
@ -54,4 +54,7 @@ PASSWORD = password
DATABASE = app
POOL_SIZE = 5
[ProxyConf]
NGINX_PROXY = False
[SqlCacheConf]

View File

@ -64,6 +64,8 @@ class JwtConf(metaclass=BaseMetaConf):
JWT_ALGORITHM: str = 'HS256'
JWT_EXPIRE_MINUTES: int = 1440
class ProxyConf(metaclass=BaseMetaConf):
NGINX_PROXY: bool = False
class SqlDbConf(metaclass=BaseMetaConf):
RDB_TYPE: str

View File

@ -1,5 +1,6 @@
import feffery_antd_components as fac
from dash import html
from common.constant import HttpStatusConstant
def render():
@ -8,7 +9,7 @@ def render():
html.Div(
[
fac.AntdResult(
status='403',
status=str(HttpStatusConstant.UNAUTHORIZED),
title='您没有权限访问该页面',
subTitle='如需访问,请联系系统管理员',
style={'paddingBottom': 0, 'paddingTop': 0},

View File

@ -1,5 +1,6 @@
import feffery_antd_components as fac
from dash import html
from common.constant import HttpStatusConstant
def render():
@ -8,14 +9,12 @@ def render():
html.Div(
[
fac.AntdResult(
status='404',
status=str(HttpStatusConstant.NOT_FOUND),
title='页面不存在',
subTitle='检查您的网址输入是否正确',
style={'paddingBottom': 0, 'paddingTop': 0},
),
fac.AntdButton(
'回到首页', type='link', href='/', target='_self'
),
fac.AntdButton('回到首页', type='link', href='/', target='_self'),
],
style={'textAlign': 'center'},
)

View File

@ -3,6 +3,7 @@ from config.dashgo_conf import ShowConf, FlaskConf, CommonConf, PathProj
from common.utilities.util_logger import Log
from common.exception import global_exception_handler
from common.utilities.util_dash import CustomDash
from common.constant import HttpStatusConstant
from i18n import t__other
@ -32,13 +33,23 @@ server = app.server
def download_file(user_name):
file_name = f'{user_name}.jpg'
if '..' in user_name:
logger.warning(f'有人尝试通过头像文件接口攻击URL:{request.url}IP:{request.remote_addr}')
abort(403)
abort(HttpStatusConstant.FORBIDDEN)
else:
return send_from_directory(PathProj.AVATAR_DIR_PATH, file_name)
# 首页拦截器
# nginx代理后拦截直接访问
@server.before_request
def ban_bypass_proxy():
from config.dashgo_conf import ProxyConf
if ProxyConf.NGINX_PROXY and request.headers.get('X-Forwarded-For') is None:
abort(HttpStatusConstant.FORBIDDEN)
# 首页重定向
@server.before_request
def main_page_redirct():
if request.path == '/':
@ -49,8 +60,10 @@ def main_page_redirct():
@server.before_request
def ban_admin():
if request.path.startswith('/admin'):
logger.warning(f'有人尝试访问不存在的管理页面URL:{request.url}IP:{request.remote_addr}')
abort(403)
from common.utilities.util_browser import get_browser_info
browser_info = get_browser_info()
logger.warning(f'有人尝试访问不存在的管理页面URL:{browser_info.url}IP:{browser_info.request_addr}')
abort(HttpStatusConstant.NOT_FOUND)
# 获取用户浏览器信息
@ -60,9 +73,9 @@ def get_user_agent_info():
browser_info = get_browser_info()
if browser_info.type == 'ie':
return "<h1 style='color: red'>IP:{}, {}</h1>".format(browser_info.ip, t__other('请不要使用IE内核浏览器'))
elif browser_info.type == 'chrome' and browser_info.version < 88:
return "<h1 style='color: red'>IP:{}, {}</h1>".format(browser_info.request_addr, t__other('请不要使用IE内核浏览器'))
elif browser_info.type == 'chrome' and browser_info.version is not None and browser_info.version < 88:
return "<h1 style='color: red'>IP:{}, {}</h1>".format(
browser_info.ip,
browser_info.request_addr,
t__other('Chrome内核版本号太低请升级浏览器'),
)