Django @csrf_exempt not working in class View

前端 未结 3 613
半阙折子戏
半阙折子戏 2021-01-11 21:43

I have an application in Django 1.9 that uses SessionMiddleware. I would like to create an API for this application inside the same project, but when doing a POST request it

相关标签:
3条回答
  • 2021-01-11 21:58

    DO NOT USE csrf_exempt with Django REST framework.

    This won't work because the SessionAuthentication enforces the csrf check anyway.

    Please make sure you use the csrf token in your AJAX requests. Django has a comprehensive documentation about it

    0 讨论(0)
  • 2021-01-11 22:12

    I found out the way to solve this. You need to create a middleware that calls before any Session Middlewares and then check against your desired urls or app to exempt the CSRF token validation. So, the code would be like this:

    settings.py

    MIDDLEWARE_CLASSES = [
        'api.middleware.DisableCSRF',  # custom middleware for API
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.cache.UpdateCacheMiddleware',
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'a9.utils.middleware.LocaleMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'a9.core.access.middleware.AccessMiddleware',
        'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'django.middleware.cache.FetchFromCacheMiddleware',
    ]
    

    urls.py

    app_name = "api"
    
    urlpatterns = [
        url(r'^v1/', include([
            url(r'^', include(router.urls)),
            url(r'^auth/', MyAuthentication.as_view()),
            url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
            url(r'^admin/', include(admin.site.urls)),
        ])),
    ]
    

    csrf_disable.py

    from django.core.urlresolvers import resolve
    
    
    class DisableCSRF(object):
        """Middleware for disabling CSRF in an specified app name.
        """
    
        def process_request(self, request):
            """Preprocess the request.
            """
            app_name = "api"
            if resolve(request.path_info).app_name == app_name:
                setattr(request, '_dont_enforce_csrf_checks', True)
            else:
                pass  # check CSRF token validation
    

    This will only check CSRF token against a specific app or url without removing all the CSRF. Also, this is django-rest-framework independent :)

    0 讨论(0)
  • 2021-01-11 22:12

    You need to decorate the csrf_exempt inside the dispatch method.

    class MyView(FormView):
    
        @method_decorator(csrf_exempt)
        def dispatch(self, *args, **kwargs):
            return super(MyView, self).dispatch(*args, **kwargs)
    
        def post(self, request, *args, **kwargs):
            # ....
            return super(MyView, self).post(request, *args, **kwargs)
    
    0 讨论(0)
提交回复
热议问题