Запрещено (куки CSRF не установлены.) при попытке подключения из настольного приложения

Я разрабатываю настольное приложение, в котором пользователи могут входить в систему, используя учетные данные из базы данных моего Django-сайта. Цель состоит в том, чтобы пользователи могли создавать сообщения на сайте Django (форум) через настольное приложение.

В коде настольного приложения есть следующий код, который успешно извлекает CSRF-токен из Django:

def get_csrf_token():
    
    # Make a GET request to your Django server to fetch the CSRF token
    response = requests.get('http://127.0.0.1:8000/accounts/get-csrf-token/')
     
    # Check if the request was successful (status code 200)
    if response.status_code == 200:
        # Extract the CSRF token from the response JSON
        csrf_token = response.json().get('csrf_token')
        print("CSRF TOKEN: ", csrf_token)
        return csrf_token
    else:
        # Handle errors, such as failed requests
        print(f"Failed to fetch CSRF token. Status code: {response.status_code}")
        return None

И следующий код, который должен отправить данные (имя пользователя, пароль, CSRF-токен) в Django:

def login(self):

        # Retrieve username and password from input fields
        username = self.username_input.text()
        password = self.password_input.text()   
               
        # Send login request to Django server
        url = "http://127.0.0.1:8000/accounts/login/"
        data = {
            "username": username, 
            "password": password,
            }
        
        # Define the headers with the CSRF token
        headers = {
            'X-CSRFToken': get_csrf_token()
        }
        print("x-csrftoken: ", headers['X-CSRFToken'])
        response = requests.post(url, data=data, headers=headers)
        
        if response.status_code == 200:
            # Authentication successful
            self.accept()
        else:
            # Authentication failed
            QMessageBox.warning(self, "Login Failed", "Invalid username or password")

Приведенный выше код отправляет запрос на адрес http://127.0.0.1:8000/accounts/login/, который связан с CustomLoginView в моем urls.py:

path('login/', CustomLoginView.as_view(template_name='accounts/login.html'), name='login')

А это код в моем файле views.py:

class CustomAuthenticationForm(AuthenticationForm):
    def clean_username(self):
        print("Entering clean_username method.......") 
        username = self.cleaned_data.get('username')
        if username:
            # Perform a case-insensitive lookup for the username
            return CustomUser.objects.filter(username__iexact=username).first()
        return None

class CSRFTokenView(APIView):
    authentication_classes = [SessionAuthentication]

    def get(self, request, format=None):
        print("Entering get method......")
        csrf_token = get_token(request)
        print("csrf token inside get method of CSRFTokenView: ", csrf_token)
        return Response({'csrf_token': csrf_token})

    
class CustomLoginView(LoginView):
     
    authentication_form = CustomAuthenticationForm
    
    def get_success_url(self):
        print("Entering get_success_url method......")
        return reverse_lazy('thread_list')

Когда я пытаюсь войти в систему через настольное приложение, я получаю следующее сообщение от Django:

Forbidden (CSRF cookie not set.): /accounts/login/
"POST /accounts/login/ HTTP/1.1" 403 2869

И я не получаю сообщения о печати из CustomAuthenticationForm и CustomLoginView.

Это в моем файле settings.py:

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',
]

Я пробовал закомментировать 'django.middleware.csrf.CsrfViewMiddleware', из settings.py. Я пробовал добавить декоратор csrf_exempt к CustomLoginView:

@method_decorator(csrf_exempt, name='dispatch')
class CustomLoginView(LoginView):
    def post(self, request, *args, **kwargs):
        if request.method == 'POST':
            print("Received POST data:", request.POST)
            print("Received headers:", request.headers)
        return super().post(request, *args, **kwargs)
    
    
    authentication_form = CustomAuthenticationForm
    
    def get_success_url(self):
        print("get_success_url method......")
        return reverse_lazy('thread_list')

Я пробовал добавить csrf_exempt в urls.py path.

Я даже пробовал удалить {% csrf_token %} из формы входа. Но я продолжаю получать одно и то же сообщение.

Решили ее.

Я вошел в систему через веб-сайт, и CustomLoginView выдал на печать следующие утверждения:

print("Received POST data:", request.POST)
print("Received headers:", request.headers)

Выяснилось, что CSRF-токен был отправлен как в данных, так и в заголовках.

Поэтому я изменил код в настольном приложении следующим образом:

url = "http://127.0.0.1:8000/accounts/login/"

        csrf_token = get_csrf_token()

        data = {
            "csrfmiddlewaretoken": csrf_token,
            "username": username, 
            "password": password,
            }
        
        headers = {
        'Cookie': f'csrftoken={csrf_token}',
        }
           
        response = requests.post(url, data=data, headers=headers)

И это решило проблему.

Вернуться на верх