Как изменить стандартную аутентификацию 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 включает некоторые заголовки по умолчанию, что устраняет проблему.