Reputation: 55
I am following this tutorial https://www.valentinog.com/blog/drf/ and succesfully finished it. I am trying to add a POST functionality to this tutorial. The thing is I am having trouble adding the POST command to send a csrf value to the server using the Axios ajax framework.
I have obtained the csrf on the cookies, and stored it in "csrfmiddlewaretoken" variable followed by a test message embedded in a json format to the axios function but it doesn't work resulting in a 403 error. I added @ensure_csrf_cookie decorator to the views.py but still the same error.
Using the @csrf_exempt decorator on views.py solves this however I want to use csrf for security.
Im using Django Version 3.0.8 on a venv
csrftoken.js
import React from "react";
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();
if (cookie.substring(0, name.length + 1) === name + "=") {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie("csrftoken");
const CSRFToken = () => {
return <input type="hidden" name="csrfmiddlewaretoken" value={csrftoken} />;
};
export default CSRFToken;
App.js
...
import axios from "axios";
import CSRFToken from "./csrftoken";
...
sendPost() {
var jsonPost = {
csrfmiddlewaretoken: document.getElementsByTagName("input")[
"csrfmiddlewaretoken"
].value,
transmitter: "This is houston Do you hear me Copy ",
};
axios({
method: "post",
url: "/api/sendpost/",
data: jsonPost,
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
...
render() {
return (
<ul>
<CSRFToken />
{this.state.data.map((contact) => {
return (
<div>
<li key={contact.id}>
{contact.name} - {contact.email}
</li>
<button onClick={() => this.sendPost()}>
Send A Post Message
</button>
</div>
);
})}
</ul>
);
}
leads app views.py
from django.views.decorators.csrf import csrf_exempt,ensure_csrf_cookie
from django.http import JsonResponse
#@csrf_exempt
@ensure_csrf_cookie
def receivePost(request):
print(request.POST)
data = {
"receiver":"Received Houston"
}
return JsonResponse(data)
settings.py
...
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
'rest_framework.authentication.TokenAuthentication',
),
}
...
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('api/lead/', views.LeadListCreate.as_view() ),
path('api/sendpost/', views.receivePost ),
]
Edit: It seems that print(request.POST) returns an empty Querydict {} even when enabling @csrf_exempt on views.py
Upvotes: 3
Views: 1392
Reputation: 806
When you make a post request to the backend, it has to be protected to prevent any modification that happen to the data from hackers that might intercept the request going from client to server, thus, csrf token exist so that each request is encrypted with a anonymous string that contains symbols, letters, and numbers.
now that you understand what the csrf token for, you need to know that when sending a request, the request need to have a csrf token with it, so that the backend can compare that token with the one stored in the server
and thus, your mistake was in the axios call in which you forgot to add csrftoken to the POST call
the code solution is:
import Cookies from 'js-cookie'
axios.post(
'/api/sendpost/',data, {headers:{'X-CSRFToken':Cookies.get('csrftoken')}})
.then((res)=>{
console.log(res)
})
.catch((e)=>{console.log(e)})
note that i am using js-cookie module which is used to handle cookies.
Upvotes: 0