在开发中,如果csrf cookie在dev工具的应用程序选项卡中不可用,它通常会被设置,但是在生产中,每当我试图创建一个新的帖子时,它会告诉我“CSRF Failed: CSRF token from the 'X-Csrftoken' HTTP header has incorrect length.
“然而,这里的情节扭曲,是与其他帖子请求,如当您登录或注册时,它工作得很完美,很好,所以我认为这似乎是django中的create
方法的问题(但是对于login,即使login工作得很好,并且我使用基于会话的身份验证登录,似乎session_id和csrf在应用程序选项卡中是不可见的?
我认为这是因为网站正在生产,出于安全原因,它不会显示会话ID。
但是,每当我尝试创建帖子失败后查看网络选项卡时,x-csrftoken
看起来像undefined
但是,存在另一个称为cookie
的密钥,其包括csrftoken
和session_id
请注意,这只发生在生产中,我从未在开发服务器上遇到过这样的问题,请查看settings.py视图代码后的www.example.com代码以了解更多说明(我为需要允许csrf令牌的域添加了https://somedomain.com)
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)
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.")
现在在前端:
let handleSubmit = (e)=>{
e.preventDefault()
console.log(Cookies.get('csrftoken'))
axios.post('https://somedomain.com/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})
},[])
settings.py 代码:
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','https://somedomain.com/']
SECURE_SSL_REDIRECT = True
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = 60
CUSTOM_HEADERS = (
'Access-Control-Allow-Origin',
'Token',
'User-Type'
)
CORS_ALLOW_HEADERS = default_headers + CUSTOM_HEADERS
CSRF_COOKIE_SAMESITE = 'none'
1条答案
按热度按时间pw9qyyiw1#
我忘了回答这个问题,基本上前端是在一个不同的子域服务,所以cookie相同的规则需要设置为
None
,在settings.py
:将CSRF_COOKIE_SAMESITE = 'Strict'
更改为CSRF_COOKIE_SAMESITE = 'None'
此外,如果您使用基于会话的身份验证(默认情况下,需要csrf令牌用于发布请求,请阅读此处的文档),请不要忘记添加:
SESSION_COOKIE_SAMESITE = 'None'
在settings.py
中