Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.4k views
in Technique[技术] by (71.8m points)

fetch - post to django API returns 403 (Forbidden) when authenticated, but able post when not authenticated

I'm building an app that works as follows:

  • Users fill out data on an html form and submit.
  • the data is posted onto the API (via Fetch).

This app uses django, django rest frame work with plain html and vanilla jav My issue is that when the user is authenticated on the API/backend, I cannot post. It returns 403. However, when I am not authenticated I can post data from the form.

Here is the JS on the form.html that posts data into the 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>

views.py

from app_reports.models import (
FlightSafetyReport
)

from .serializers import (
FlightSafetyReportSerializer
)

class FlightSafetyReportViewSet(viewsets.ModelViewSet):

    serializer_class = FlightSafetyReportSerializer
    queryset = FlightSafetyReport.objects.all()

settings.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"

To re-iterate, when I am not logged into the api / when I am not logged into django-admin I am able to post. When I am logged in, I get a 403 forbidden error.

question from:https://stackoverflow.com/questions/66064761/post-to-django-api-returns-403-forbidden-when-authenticated-but-able-post-whe

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here is what I I think is happening to your requests. The problem might be that you are passing an invalid csrftoken. I have created a duplicate of your code on my side and it works. It starts giving me 403 error when I change csrftoken value to some random value. Like below check it out.

var csrftoken = getCookie('csrftoken');
    csrftoken = "blacjcjsjsjss";

It then gives the 403 Forbidden error in the console. If I remove the line csrftoken = "blacjcjsjsjss"; it starts working again. What I am saying is that your csrftoken value is some how wrong. You need to make sure that you are getting the correct crsftoken.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...