2017-01-18 7 views
1

私はDjango 1.9にSessionMiddlewareを使用するアプリケーションを持っています。私は同じプロジェクトの内部でこのアプリケーション用の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 **の代わりに** View **をインポートしようとしましたか? –

+0

** TemplateView **のポスト方法はありません。 –

+0

はい、それが最初の試みでした。実際、TemplateViewはViewから継承しているため、postメソッドがあります:https://docs.djangoproject.com/en/1.9/ref/class-based-views/base/#django.views.generic.baseTemplateView – 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トークンをチェックするだけです。また、これはdjango-rest-frameworkに依存しません:)

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

Django RESTフレームワークでcsrf_exemptを使用しないでください。

SessionAuthenticationがとにかくcsrfチェックを強制するため、これは機能しません。

AJAXリクエストでcsrfトークンを使用していることを確認してください。 Djangoはそれについてa comprehensive documentationを持っています

+0

質問で触れたように、他のクライアントがエンドポイントを消費できるようにするには、APIアプリケーションのcsrfトークンを免除する必要があります。問題はAJAXリクエストではなく、既存のプロジェクトからセッションミドルウェアを削除することなく、セッションミドルウェアを他のアプリケーション、つまりモバイル向けに動作させる方法です。 – Carlos

+0

あなたはそれが間違っています。トークン認証またはOAuthは、ブラウザ以外のクライアントに使用する必要があります。 – Linovia

+0

私はあなたが実際にその質問を理解するとは思わない。 APIはAJAXリクエストとは異なります。 AJAXリクエストは、エンドポイントを消費するためのものであり、APIを作成するものではありません。 – Carlos

関連する問題