django - post to django API 在经过身份验证时返回 403 (Forbidden),但在未经过身份验证时可以发布
问题描述
我正在构建一个应用程序,其工作方式如下:
- 用户在 html 表单上填写数据并提交。
- 数据发布到 API(通过 Fetch)。
这个应用程序使用 django、django rest 框架与纯 html 和 vanilla jav 我的问题是,当用户在 API/后端进行身份验证时,我无法发布。它返回 403。但是,当我未通过身份验证时,我可以从表单中发布数据。
这是 form.html 上的 JS,它将数据发布到 API:
<script>
console.log('js linked')
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var 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;
}
var csrftoken = getCookie('csrftoken');
console.log(csrftoken)
function post_report(event) {
event.preventDefault();
var contact_email = document.getElementById("contact_email").value
var contact_number = document.getElementById("contact_number").value
var date_time = document.getElementById("date_time").value
var location = document.getElementById("location").value
var description = document.getElementById("description").value
console.log(contact_email + ' ' + description)
fetch("http://127.0.0.1:8000/api/Flight_Safety_Reports/",{
method: "POST",
mode: 'same-origin',
headers:{
"Accept": "application/json",
'Content-Type':'application/json',
'X-CSRFToken': csrftoken
},
body: JSON.stringify({
contact_email:contact_email,
contact_number:contact_number,
date_time:date_time,
location:location,
description:description
})
})
.then(response =>console.log(response))
alert('report submitted')
}
</script>
视图.py
from app_reports.models import (
FlightSafetyReport
)
from .serializers import (
FlightSafetyReportSerializer
)
class FlightSafetyReportViewSet(viewsets.ModelViewSet):
serializer_class = FlightSafetyReportSerializer
queryset = FlightSafetyReport.objects.all()
设置.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'crispy_forms',
'bootstrap4',
'rest_framework',
'corsheaders',
'articles',
'user_api',
'app_sandbox',
'django.contrib.sites',
'allauth',
'allauth.account',
'allauth.socialaccount',
'rest_auth',
'rest_auth.registration',
'rest_framework.authtoken',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'corsheaders.middleware.CorsMiddleware',
]
ROOT_URLCONF = 'djreact.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BUILD_DIR, BACKEND_TEMPLATES_DIR],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'djreact.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/3.1/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/
STATIC_URL = '/static/'
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
]
}
CORS_ORIGIN_ALLOW_ALL = True
STATICFILES_DIRS = [os.path.join(BUILD_DIR,'static')]
CSRF_COOKIE_NAME = "XSRF-TOKEN"
重新迭代,当我没有登录到 api 时/当我没有登录到 django-admin 时,我可以发布。当我登录时,我收到 403 禁止错误。
解决方案
这是我认为您的请求正在发生的事情。问题可能是您传递了无效的 csrftoken。我在我这边创建了你的代码的副本,它可以工作。403
当我将 csrftoken 值更改为某个随机值时,它开始给我错误。像下面检查一下。
var csrftoken = getCookie('csrftoken');
csrftoken = "blacjcjsjsjss";
然后它在控制台中给出 403 Forbidden 错误。如果我删除该行csrftoken = "blacjcjsjsjss";
,它会再次开始工作。我要说的是您的 csrftoken 值有些错误。您需要确保获得正确的 crsftoken。
推荐阅读
- libgdx - 如何在不先单击的情况下使 libGDX 滚动窗格滚动
- sql - SQL查询将表分组为表?
- php - Symfony EasyAdminBundle 3 覆盖 createIndexQueryBuilder()
- python - 如何用分离的特征计算和绘图?
- django - 十进制字段形式的变量 min_value
- python - 如何将子字符串括在方括号中python
- continuous-integration - Bitbucket PR 评论可以触发 CI/CD 操作吗?
- python-3.x - 如何获得嵌套的scrapy - 选择器
- c - C中的while循环迭代问题
- javascript - Javascript 移位数组的值