简体   繁体   English

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

[英]{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)即使提供了 csrf,它在前端根本无法识别它(注意它在后端完美运行,但不是前端)

views.py:视图.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:我还有一个接收 csrf 令牌的资源:

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

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

in urls.py:在 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 csrf 正在开发控制台中打印

any idea?任何想法?

EDIT my csrf settings, since someone requested in the comments:编辑我的 csrf 设置,因为有人在评论中要求:

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:编辑:我发现在 settings.py 我在 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这就是导致问题的原因,但是如果我尝试更改为BasicAuthentication之类的,即使我登录了,我也会未经授权

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 的要求不正确。

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 API

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

If match one by one.如果一一匹配。

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

data - post (I guess this is the variable where data are saved, I suggest you rename it) data - post(我猜这是保存数据的变量,我建议你重命名它)

config - {withCredentials:true}配置 - {withCredentials:true}

Until I understand your cookie is sent (due to withCredentials:true ), but your header not.直到我了解您的 cookie 已发送(由于withCredentials:true ),但您的标头未发送。 They are ignored by axios. 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.如果需要,可以将xsrfHeaderName: 'X-CSRFToken'xsrfCookieName: 'csrftoken'添加到对象中。 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.您可以在 DevTools > Network 中验证它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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