2017-01-18 4 views
1

저는 SessionMiddleware를 사용하는 Django 1.9에 응용 프로그램을 가지고 있습니다. 동일한 프로젝트 내에서이 애플리케이션에 대한 API를 만들고 싶습니다만 POST 요청을 할 때 @csrf_exempt 주석이 작동하지 않습니다. 내가 요청을하고있는 중이 야Django @csrf_exempt가 클래스에서 작동하지 않습니다.보기

은 우체부를 던져 그리고 이것은 내가 지금까지 무엇을 가지고 :

settings.py

MIDDLEWARE_CLASSES = [ 
    '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',  
] 

OAUTH2_PROVIDER = { 
    # this is the list of available scopes 
    'SCOPES': {'read': 'Read scope', 'write': 'Write scope', 'groups': 'Access to your groups'} 
} 

CORS_ORIGIN_ALLOW_ALL = True 
CORS_ALLOW_METHODS = (
    'DELETE', 
    'GET', 
    'OPTIONS', 
    'PATCH', 
    'POST', 
    'PUT', 
) 
CORS_ALLOW_HEADERS = (
    'accept', 
    'accept-encoding', 
    'authorization', 
    'content-type', 
    'dnt', 
    'origin', 
    'user-agent', 
    'x-csrftoken', 
    'x-requested-with', 
) 

REST_FRAMEWORK = { 
    # Use Django's standard `django.contrib.auth` permissions, 
    # or allow read-only access for unauthenticated users. 
    'DEFAULT_PERMISSION_CLASSES': [ 
     'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly', 
     #'rest_framework.permissions.IsAuthenticated', 
    ], 
    'DEFAULT_AUTHENTICATION_CLASSES': (
     'oauth2_provider.ext.rest_framework.OAuth2Authentication', 
     #'rest_framework.authentication.TokenAuthentication', 
    ) 
} 

urls.py

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)), 
    ])), 
] 

전망 .py

@method_decorator(csrf_exempt, name='dispatch') 
class MyAuthentication(TemplateView): 

    def post(self, request, *args, **kwargs): 

     return HttpResponse('Hello, World!') 

이 후에는 항상 CSRF 확인에 실패했습니다.

나는이 질문을 django-rest-framework의 IRC 채널에서 물었지만 아직 대답이 없습니다. 제발, 어떤 조언을 매우 극명하게 될 것입니다.

+0

클래스 내에서 ** TemplateView ** 대신 **보기 ** 가져 오기를 시도 했습니까? –

+0

** TemplateView **에 사용할 수있는 게시 방법이 없습니다. –

+0

예, 처음 시도했습니다. 실제로, TemplateView는 View에서 상속받습니다. 따라서 Post 메소드가 있습니다 : https://docs.djangoproject.com/en/1.9/ref/class-based-views/base/#django.views.generic.base.TemplateView – Carlos

답변

0

나는 이것을 해결하는 방법을 발견했다. 세션 미들웨어를 호출하기 전에 미들웨어를 생성하고 CSRF 토큰 유효성 검사를 면제하기 위해 원하는 URL이나 앱을 확인해야합니다. 그래서, 코드는 다음과 같습니다

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 

모든 CSRF를 제거하지 않고 특정 앱 또는 URL에 대한 CSRF 토큰 만 확인합니다. 또한, 이것은 장고 - 나머지 프레임 워크에 독립적입니다 :)

0

방법 안에 csrf_exempt을 장식해야합니다.

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

이것이 @method_decorator (csrf_exempt, name = 'dispatch')가 수행하는 것입니다. – Carlos

0

장고 REST 프레임 워크와 함께 csrf_exempt을 사용하지 마십시오.

SessionAuthentication이 csrf 검사를 시행하기 때문에 작동하지 않습니다.

AJAX 요청에 csrf 토큰을 사용해야합니다. 장고 그것에 대해 a comprehensive documentation있다

+0

질문에서 언급했듯이 다른 클라이언트가 끝점을 사용할 수있게하려면 API 응용 프로그램의 csrf 토큰을 면제해야합니다. 문제는 AJAX 요청이 아니라 세션 미들웨어를 기존 애플리케이션에서 제거하지 않고 다른 애플리케이션 (예 : 모빌)에서 작동시키는 방법에 관한 것입니다. – Carlos

+0

그러면 잘못 이해하게됩니다. 비 브라우저 클라이언트에는 토큰 인증 또는 OAuth를 사용해야합니다. – Linovia

+0

나는이 질문을 실제로 이해하지 못한다고 생각합니다. API는 AJAX 요청을 수행하는 것과 다릅니다. AJAX 요청은 API를 만들지 말고 끝점을 사용하기위한 것입니다. – Carlos