[DRF] CSRF, csrf_exempt 에 대한 정리.
- view에 대한 정리를 하면서 django rest framework에서 CSRF의 에러와 설정에 대한 글을 상당히 많이 볼 수 있었다.
- 하지만, 대부분의 글들이 써야 하는게 맞는지, 어떤 경우에 쓰는게 맞는지에 대한 정보가 매우 부족했다.
- 어처구니 없던건 뤼튼(https://wrtn.ai/)과 chatgtp 둘 다의 답변이 오류로 나왔다는 것이다. 같은 질문과 오류에 대해 잘못된 정보라는걸 알려주고 검토를 요청했는데도 오류로 나왔다
- 오류 내용으로 APIView 혹 @api_view를 사용하게 되면 자동으로 CSRF 검증이 비활성 되는게 맞냐는 질문이었다.
- 답변으로 비활성화되지 않는다고 나왔다.
- csrf_exempt를 사용해야 하는 경우는, @api_view 데코레이션을 사용하는 FBV나 APIView 등을 사용하는 CBV가 아닌 일반 django 함수나 클래스를 사용하면서 rest를 구현하는 경우에 한해서 요구가 된다.
- 사용 방법은 아래와 같다.
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def my_view(request):
return HttpResponse('Hello world')
- drf에서 csrf_exempt가 비활성화 되는 코드는 as_view 함수의 return 부분이다.
@classmethod
def as_view(cls, **initkwargs):
"""
Store the original class on the view function.
This allows us to discover information about the view when we do URL
reverse lookups. Used for breadcrumb generation.
"""
if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
def force_evaluation():
raise RuntimeError(
'Do not evaluate the `.queryset` attribute directly, '
'as the result will be cached and reused between requests. '
'Use `.all()` or call `.get_queryset()` instead.'
)
cls.queryset._fetch_all = force_evaluation
view = super().as_view(**initkwargs)
view.cls = cls
view.initkwargs = initkwargs
# Note: session based authentication is explicitly CSRF validated,
# all other authentication is CSRF exempt.
return csrf_exempt(view)
- drf에서 csrf가 필요하지 않는 이유로 이미 토큰을 사용하여 csrf의 변조를 방지하는 동일한 역할을 수행하기 때문이라고 한다. 관련된 정보가 drf 공식 사이트에는 없고 다른 사람의 포스팅을 통해 얻은 정보이기에 부정확 할 수 있다. 하지만 동일한 내용이 스택오버플로우 및 몇곳의 사이트에 있는 만큼 본인은 이렇게 이해를 하고자 한다.
- reference :
https://stackoverflow.com/questions/30871033/django-rest-framework-remove-csrf/30872613
https://www.reddit.com/r/django/comments/s3om3a/csrf_toke_in_django_rest_framework/