Django-Rest + React 前端:CORS 问题
Posted
技术标签:
【中文标题】Django-Rest + React 前端:CORS 问题【英文标题】:Django-Rest + React Frontend : CORS issue 【发布时间】:2021-10-24 07:31:16 【问题描述】:我有一个 Django REST 后端(目前以 http://localhost:8000
运行)和一个 React 前端(在 http://localhost:3000
上),我正在努力让跨域认证工作。
我在这里读到的大多数解决方案(例如,参见1 或2)都是针对CORS_ORIGIN_ALLOW_ALL = True
和CORS_ALLOWED_ORIGINS = [*]
,但这不是我想做的事情。
我希望它对生产安全,并了解如何正确设置 csrf 身份验证。
错误信息:
在 Django 控制台中我看到:
[24/Aug/2021 13:48:18] "OPTIONS /calc/ HTTP/1.1" 200 0
Forbidden (CSRF cookie not set.): /calc/
在我的浏览器中:
Failed to load resource: the server responded with a status of 403 (Forbidden)
文件:
Django REST API:
我已经安装了django-cors-headers
。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'corsheaders',
'maapi', # This is my app
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware', # Cors header are here
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
[...]
CORS_ORIGIN_ALLOW_ALL = False
CORS_ALLOWED_ORIGINS = [
"http://127.0.0.1:3000",
"http://localhost:3000",
]
CORS_ALLOW_CREDENTIALS = True
CSRF_TRUSTED_ORIGINS = [
"http://127.0.0.1:3000",
"http://localhost:3000",
]
maapi/views.py:
class Calc(View):
"""
Run a static simulation.
"""
def post(self, request, *args, **kwargs):
rjson = json.loads(request.body)
try:
# do things
return JsonResponse(results)
except Exception as e:
return e, 500
urls.py:
from maapi import views
router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)
urlpatterns = [
path('admin/', admin.site.urls),
path('calc/', views.Calc.as_view(), name='calc'),
# path('calc/', ensure_csrf_cookie(views.Calc.as_view()), name='calc'), # I tried this one too without more success
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
path('', include(router.urls)),
]
反应前端:
我用的是教程here。
CrsfToken.js:import React from 'react';
function getCookie(name)
let cookieValue = null;
if (document.cookie && document.cookie !== '')
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++)
const cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '='))
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
return cookieValue;
const csrftoken = getCookie('csrftoken');
const FormCsrfToken = () =>
return (
<input name="csrfmiddlewaretoken" value=csrftoken type="hidden" />
);
;
export default FormCsrfToken;
export csrftoken
App.js:
import csrftoken from './CsrfToken';
function App()
[...]
const getdata = () =>
setFetching(true);
const bod =
// Things
;
fetch("http://localhost:8000/calc/",
method: "POST",
credentials: 'include',
mode: 'cors',
headers:
'Accept': 'application/json',
"Content-Type": "application/json",
'X-CSRFToken': csrftoken,
,
body: JSON.stringify(bod),
)
.then((response) =>
return response.json();
)
.then((d) =>
// Do things
)
.catch((object) =>
setFetching(false);
openNotification();
);
;
你能发现缺少的东西吗?
【问题讨论】:
【参考方案1】:我已经解决了:
只需将您的 CSRF_TRUSTED_ORIGINS
更改为:
CSRF_TRUSTED_ORIGINS = [
"127.0.0.1:3000",
"localhost:3000",
]
还有一件事,不要在请求中发送csrftoken
。你不需要它。你可以删除它。
【讨论】:
谢谢,我试过了,但没有任何改变,我仍然有同样的问题Forbidden (CSRF cookie not set.): /calc/
(前端有或没有csrftoken
)。
尝试从您的 fetch 请求中删除 credentials:'include'
并从您的 settings.py 中删除 CORS_ALLOW_CREDENTIALS
谢谢,但在从请求中删除凭据和 CORS_ALLOW_CREDENTIALS
时仍然出现相同的错误 Forbidden (CSRF cookie not set.): /calc/
。以上是关于Django-Rest + React 前端:CORS 问题的主要内容,如果未能解决你的问题,请参考以下文章
使用 angularjs 进行 django-rest 分页
使用 angular 向 django-rest 发送 DELETE 请求被解释为 OPTIONS
使用 django-rest 框架中的 GET 方法将 url 作为参数传递?