Как изменить стандартную аутентификацию Django в forntend

Я работаю над проектом, в back-end мы используем Django с Rest и для front мы используем Wordpress и мы хотим отправить otp для пользователя и если OTP код от пользователя является действительным, то войти в систему пользователя и сохранить CSRF-токен и так далее ..

но вот в чем проблема, я не хотел сохранять opt в таблице и в chatgpt было предложено сохранить его в сессии или в памяти, я хотел попробовать сессионный способ, но столкнулся с проблемой: после вызова /send_otp/ и получения otp мне нужно вызвать /login/ и проверить, является ли otp mach, но в login он возвращает otp из сессии None и я могу получить доступ к сессии, которую я сохранил в send_otp

это две функции send_otp и login :

class SendOTPView(APIView):
    def post(self, request):
        serializer = OTPSerializer(data=request.data)
        if serializer.is_valid():
            phone_number = serializer.validated_data["phone"]
            otp_code = randint(100000, 999999)
            request.session['otp_code'] = otp_code
            print("otp in sendOTP",request.session.get("otp_code"))
            otp_send(phone_number, otp_code)
            return Response(
                {"detail": "OTP sent successfully"}, status=status.HTTP_200_OK
            )
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class UserLoginView(APIView):
    def post(self, request):
        serializer = UserLoginSerializer(data=request.data)
        if serializer.is_valid():
            stored_otp = request.session.get("otp_code")
            print(stored_otp)
            user_entered_otp = serializer.validated_data["otp"]
            phone_number = serializer.validated_data["phone"]
            try:
                user_from_db = User.objects.get(username=phone_number)
            except:
                return Response({"detail": "user not found"}, status=status.HTTP_404_NOT_FOUND)
            password = generate_password(phone_number)
            if str(user_entered_otp) == str(stored_otp):
                del request.session['otp_code']
                user = authenticate(username=phone_number, password=password)

                if user:
                    return Response({"detail": 'logged in successfully '}, status=status.HTTP_200_OK)
                else:
                    return Response(
                        {"detail": "Invalid phone or otp"},
                        status=status.HTTP_400_BAD_REQUEST,
                    )
            else :
                return Response(
                    {
                        "detail": "Wrong otp code",
                    },
                    status=status.HTTP_400_BAD_REQUEST,)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

и вот html & js файлы (это простая версия только для тестирования):

// Base URL for the API
const baseURL = 'http://127.0.0.1:8000/auth';

// Function to get CSRF token from the cookie
function getCSRFToken() {
    const cookieValue = document.cookie
        .split('; ')
        .find(row => row.startsWith('csrftoken='))
        .split('=')[1];
    return cookieValue;
}

// Function to send OTP
function sendOTP() {
    const phone = document.getElementById('phone').value;

    fetch(`http://127.0.0.1:8000/auth/send_otp/`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-CSRFToken': getCSRFToken() // Include CSRF token in the request headers
        },
        credentials: 'include', // include cookies with the request
        body: JSON.stringify({ phone })
    })
    .then(response => {
        if (response.ok) {
            alert('OTP sent successfully');
            document.getElementById('phone-form').style.display = 'none';
            document.getElementById('otp-form').style.display = 'block';
            document.getElementById('otp-phone').value = phone; // pre-fill phone number in the OTP form
        } else {
            alert('Failed to send OTP');
        }
    })
    .catch(error => console.error('Error:', error));
}

// Function to verify OTP and login
function verifyOTP() {
    const phone = document.getElementById('otp-phone').value;
    const otp = document.getElementById('otp').value;

    fetch(`http://127.0.0.1:8000/auth/login/`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-CSRFToken': getCSRFToken() // Include CSRF token in the request headers
        },
        credentials: 'include', // include cookies with the request
        body: JSON.stringify({ phone, otp })
    })
    .then(response => {
        if (response.ok) {
            alert('Login successful');
            window.location.href = '/'; // redirect to the dashboard or desired page after login
        } else {
            alert('Failed to verify OTP');
        }
    })
    .catch(error => console.error('Error:', error));
}

и я не знаю почему, но если я делаю это в postman, я получаю результат и он проверяет код (сначала вызываю send_otp в postman, затем вызываю login), но когда я пытаюсь с html и js, я не могу

Согласно документации, добавления заголовка CSRF недостаточно. Вам также необходимо добавить заголовок Referrer, соответствующий заголовку Host, к вашему запросу для "опасных" запросов (например, POST, PUT и т. д.). Он должен указывать на ваш домен, каким бы он ни был.

Я не совсем уверен, но может быть так, что Postman включает некоторые заголовки по умолчанию, что устраняет проблему.

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