diff --git a/omniadvisor/pyproject.toml b/omniadvisor/pyproject.toml index fc384113d93e70b96fba743ee7da3f97e5bf2e07..9e6b0805a46615edb3df91ae3cf65927821a899b 100755 --- a/omniadvisor/pyproject.toml +++ b/omniadvisor/pyproject.toml @@ -23,6 +23,7 @@ requests = "^2.32.3" python-dateutil = "2.9.0.post0" psycopg2-binary = "^2.9.10" django-sslserver = "0.22" +django-csp = "4.0" keyring = "24.3.1" keyrings-alt = "5.0.2" diff --git a/omniadvisor/src/server/app/admin.py b/omniadvisor/src/server/app/admin.py index a29eebdd98d2bf8781d9bd241056fe65781b18ed..c3b7b01b14c6e7cf866934cc74a8f3382dae0bc9 100644 --- a/omniadvisor/src/server/app/admin.py +++ b/omniadvisor/src/server/app/admin.py @@ -1,5 +1,7 @@ from django.contrib import admin from django.contrib.auth.models import User, Group +from django.utils.decorators import method_decorator +from django.views.decorators.cache import never_cache from .models import DatabaseLoad, DatabaseTuningRecord, DatabaseExamRecord @@ -57,6 +59,21 @@ class BaseAdmin(admin.ModelAdmin): def has_add_permission(self, request, obj=None): return False + # 禁用change_view的缓存 + @method_decorator(never_cache) + def change_view(self, request, object_id, form_url='', extra_context=None): + return super().change_view(request, object_id, form_url, extra_context) + + # 禁用add_view的缓存 + @method_decorator(never_cache) + def add_view(self, request, form_url='', extra_context=None): + return super().add_view(request, form_url, extra_context) + + # 禁用changelist_view的缓存 + @method_decorator(never_cache) + def changelist_view(self, request, extra_context=None): + return super().changelist_view(request, extra_context) + # 定义内联模型:TuningRecord class TuningRecordInline(admin.TabularInline): # 或使用 StackedInline diff --git a/omniadvisor/src/server/engine/settings.py b/omniadvisor/src/server/engine/settings.py index a5b2ae68d794a73478eddaefc0c8be9a32e58600..919f1e4c294b2395603d3de0af74961c22135962 100644 --- a/omniadvisor/src/server/engine/settings.py +++ b/omniadvisor/src/server/engine/settings.py @@ -35,6 +35,23 @@ SESSION_COOKIE_SECURE = True SECURE_SSL_REDIRECT = True # 为了确保 Django 能正确判断请求是否是通过 HTTPS 发起的,它需要一个指示正确协议的头部。 SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') +# 禁止 JavaScript 读取 Session Cookie +SESSION_COOKIE_HTTPONLY = True +# 禁止 JavaScript 读取 CSRF Cookie +CSRF_COOKIE_HTTPONLY = True +# 浏览器关闭后清除 Session +SESSION_EXPIRE_AT_BROWSER_CLOSE = True +# 启用浏览器 XSS 过滤 +SECURE_BROWSER_XSS_FILTER = True +# 禁止 MIME 类型混淆 +SECURE_CONTENT_TYPE_NOSNIFF = True +# 禁止页面被 iframe 嵌入,防御点击劫持 +X_FRAME_OPTIONS = "DENY" +# 使用CSP防御XSS和资源注入 +CSP_DEFAULT_SRC = ("'self'", ) +CSP_SCRIPT_SRC = ("'self'", ) +CSP_STYLE_SRC = ("'self'", "fonts.googleapis.com") +CSP_FONT_SRC = ("'self'", "fonts.gstatic.com") ALLOWED_HOSTS = ['*'] diff --git a/omniadvisor/src/server/engine/urls.py b/omniadvisor/src/server/engine/urls.py index 1e05d382b8995cb18f77eeaab7a0c534267c0a8e..ea21b8a47b1eda6f9fd01752dfeefe03c60a53d3 100644 --- a/omniadvisor/src/server/engine/urls.py +++ b/omniadvisor/src/server/engine/urls.py @@ -16,7 +16,17 @@ Including another URLconf """ from django.contrib import admin from django.urls import path +from django.http import HttpResponseForbidden + + +# 拦截部分url路径 +def url_disabled(request): + return HttpResponseForbidden('This page is disabled.') + urlpatterns = [ + # 禁用Admin Password Change页面 + path('admin/password_change/', url_disabled), + # Admin页面 path('admin/', admin.site.urls), ]