简体   繁体   中英

{detail: 'CSRF Failed: CSRF token missing.'} Django and React

even though csrf is provided, it just does not recognize it at all in frontend side (note it works perfect on backend, but not frontend)

views.py:

class CheckAuthenticated(views.APIView):
    def get(self, request):
        if request.user.is_authenticated:
            return Response("Authenticated")
        else:
            return Response("Not Authenticated",status=401)
    
class PostView(viewsets.ModelViewSet):
    serializer_class = serializer.PostSerializer

    def get_queryset(self):
        queryset = models.Post.objects.all()
        return queryset
    
    @method_decorator(ensure_csrf_cookie,csrf_protect)
    def create(self,request):
        authentication_classes = [SessionAuthentication]
        permissions_classes = [IsAuthenticated]
        post = serializer.PostSerializer(data=request.data)
        if post.is_valid():
            title = post.data['title']
  
            description = post.data['description']
    
            models.Post.objects.create(title=title,description=description,user=User.objects.first())
            return Response("post created successfully.")
        return Response("post creation failed.")

i have also a resource that receive csrf token:

 
class GetCSRFToken(views.APIView):
    permission_classes = [AllowAny, ]

    
    @method_decorator(ensure_csrf_cookie)
    def get(self, request, format=None):
        return Response("Success")

in urls.py:

  urlpatterns = [
   path('csrf/',views.GetCSRFToken.as_view(),name='csrf'),
   path('isauthenticated/',views.CheckAuthenticated.as_view(),name='authenticated'),
]

now in frontend:

let handleSubmit = (e)=>{
        e.preventDefault()
        console.log(Cookies.get('csrftoken'))
        axios.post('http://127.0.0.1:8000/posts/',post,{withCredentials:true},{headers:{'X-CSRFToken':Cookies.get('csrftoken')}}).then((res)=>{
            console.log(res.data)
        }).catch((e)=>{
            console.log(e.response.data)
            console.log(Cookies.get('csrftoken'))
        })
    }
    useEffect(()=>{
        axios.get('http://127.0.0.1:8000/posts/').then((res)=>{
            setPostList(res.data)
        })
        axios.get('http://127.0.0.1:8000/csrf/',{headers:{Authorization:null},withCredentials:true})

    },[])

the csrf is being printed in the dev console

any idea?

EDIT my csrf settings, since someone requested in the comments:

ALLOWED_HOSTS = ['*']
ACCESS_CONTROL_ALLOW_ORIGIN = '*'
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
ACCESS_CONTROL_ALLOW_CREDENTIALS = True
ACCESS_CONTROL_ALLOW_METHODS = '*'
ACCESS_CONTROL_ALLOW_HEADERS = '*'

'''
SESSION_COOKIE_SECURE = True

CSRF_COOKIE_PATH = '/'
'''
CSRF_COOKIE_SAMESITE = 'Strict'  




CSRF_TRUSTED_ORIGINS = [ "http://127.0.0.1:3000",'http://127.0.0.1:8000']

EDIT : I figured out that in settings.py i have a problem with authentication in drf:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.SessionAuthentication',
    ]
}

this is what causing the problem, but if i tried to change to like BasicAuthentication i would be unauthorized even if i logged in

I guess this is half the solution, which is finding the problem.

After checked your code again, I think I figured out the problem. Your request with axios is incorrect.

axios.post(
            'http://127.0.0.1:8000/posts/',
            post,
            {withCredentials:true},
            {headers:{
                'X-CSRFToken':Cookies.get('csrftoken')}}
).then((res)=>{
            ...

Now check the Axios API .

axios.post(url[, data[, config]])

If match one by one.

url - 'http://127.0.0.1:8000/posts/'

data - post (I guess this is the variable where data are saved, I suggest you rename it)

config - {withCredentials:true}

Until I understand your cookie is sent (due to withCredentials:true ), but your header not. They are ignored by axios.

So, you have to put all the configuration in the same object. For example using a variable:

const postRequestConf = {
    withCredentials: true,
    headers: {
        'X-CSRFToken': Cookies.get('csrftoken')
    }
}

If you want, you can add xsrfHeaderName: 'X-CSRFToken' and xsrfCookieName: 'csrftoken' to the object. Check Request Config .

And the request.

axios.post(
           'http://127.0.0.1:8000/posts/',
           renamedVariable,
           postRequestConf
).then( res => {...})...

Now, the request must be sent this data. You can verify it in DevTools > Network.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM