Запрещено (куки 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)
И это решило проблему.