TL;DR
CSRF 的一个 case,原因是前端接口访问的是 api/v1/tools/wakeonlan/trigger/ ,Django URL 中设置的 path 是 api/v1/tools/wakeonlan/trigger 不匹配导致的,在 Django urls.py 中的 path 追加 / 解决。
问题描述
在开发岚枢时,新增了一个 Wake On Lan 的接口,但是报 CSRF 的错。
Reason given for failure:
Origin checking failed - http://192.168.6.5:9808 does not match any trusted origins.很奇怪,django-rest-framework 框架的请求就没这个问题。
Vite 的 Proxy 配置
// https://vite.dev/config/
export default defineConfig({
plugins: [react(), tailwindcss()],
server: {
host: "0.0.0.0",
port: 9808,
proxy: {
"/api": {
target: "http://127.0.0.1:8620",
changeOrigin: true,
},
},
},
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
css: {
preprocessorOptions: {
less: {
javascriptEnabled: true,
},
},
},
});Trae CN 的解决方案
from rest_framework.views import APIView
from django.views.decorators.csrf import csrf_exempt
...
@csrf_exempt
class WakeOnLanAPIView(APIView):
"""
Wake-on-LAN API视图
接收MAC地址并发送唤醒包
"""首先,是多引入了一次 APIView;其次,对类使用 csrf_exempt 修饰,在 urls 中使用 as_view 方法时会报错,原因是已经把类修饰为方法了。


提示还是会重复引入,还给出了其他的答案。
from django.utils.decorators import method_decorator
@method_decorator(csrf_exempt, name="dispatch")
class WakeOnLanAPIView(APIView):另外一个答案。
from django.views.decorators.csrf import csrf_exempt
urlpatterns += [
path("tools/wakeonlan/trigger/", csrf_exempt(WakeOnLanAPIView.as_view()), name="wake_on_lan_api"),
]最后都没有解决。
Cursor
Cursor 给出的答案。
diff --git a/api/urls.py b/api/urls.py
index 9e4817d..b342e0f 100644
--- a/api/urls.py
+++ b/api/urls.py
@@ -26,5 +26,5 @@ urlpatterns = [
# 工具类 API
urlpatterns += [
- path("tools/wakeonlan/trigger", WakeOnLanAPIView.as_view(), name="wake_on_lan_api"),
+ path("tools/wakeonlan/trigger/", WakeOnLanAPIView.as_view(), name="wake_on_lan_api"),
]
diff --git a/misthub/settings.py b/misthub/settings.py
index 759251f..41b346e 100644
--- a/misthub/settings.py
+++ b/misthub/settings.py
@@ -34,6 +34,13 @@ DEBUG = True
ALLOWED_HOSTS = ["*"]
+# Allow cross-origin POSTs from dev frontend origins to satisfy CSRF origin check
+CSRF_TRUSTED_ORIGINS = [
+ "http://192.168.6.5:9808",
+ "http://localhost:9808",
+ "http://127.0.0.1:9808",
+]其实只改 urls.py 文件,在 path 后面新增 / 就可以解决了。
使用 Cursor 相同提示词
回滚改动,使用和 Cursor 相同提示词,再次询问 Trae CN。

index 759251f..b595d0a 100644
--- a/misthub/settings.py
+++ b/misthub/settings.py
@@ -142,3 +142,8 @@ MEDIA_ROOT = os.path.join(BASE_DIR, "media")
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
+
+# 跨域请求配置
+CSRF_TRUSTED_ORIGINS = [
+ "http://192.168.6.5:9808",
+]
diff --git a/pyproject.toml b/pyproject.toml
index e12bad9..ef9e6a1 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -10,6 +10,7 @@ dependencies = [
"mysqlclient (>=2.2.7,<3.0.0)",
"djangorestframework (>=3.16.1,<4.0.0)",
"cryptography (>=45.0.7,<46.0.0)",
+ "django-cors-headers (>=4.4.0,<5.0.0)",
]没有发现问题,继续提示。

还是继续改 settings.py,放弃。
原因
前端接口访问的是 api/v1/tools/wakeonlan/trigger/ ,Django URL 中设置的 path 如下。
urlpatterns += [
path("tools/wakeonlan/trigger", WakeOnLanAPIView.as_view(), name="wake_on_lan_api"),
]在 path 后增加 / 就好了。