2013-05-17 6 views
13

Sto utilizzando il framework django rest per eseguire chiamate API tramite IOS e viene visualizzato il seguente errore "CSRF non riuscito: cookie CSRF non impostato."Django REST Framework CSRF non riuscito: cookie CSRF non impostato

Ecco la mia django codice API:

class LoginView(APIView): 
    """ 
    List all snippets, or create a new snippet. 
    """ 
    @csrf_exempt 
    def get(self, request, format=None): 
     startups = Startup.objects.all() 
     serializer = StartupSerializer(startups, many=True) 
     return Response(serializer.data) 

    @csrf_exempt 
    def post(self, request, format=None): 
     profile = request.POST 
.... 

Cosa posso fare?

+0

Lo hai mai capito? Non ho mai superato questo. – user798719

+0

Possibile duplicato di [Django Rest Framework rimuovi csrf] (http://stackoverflow.com/questions/30871033/django-rest-framework-remove-csrf) – user3467349

risposta

1

Per GET, non è necessario modificare i dati, quindi non è richiesto un CSRF.

Se si modificano i dati con un POST, è necessario disporre di un CSRF se si utilizza l'autenticazione basata su sessione. Altrimenti, stai aprendo un buco di sicurezza. Anche se pensi che il tuo server Django gestirà le app per iPhone, non c'è nulla che impedisca a qualcuno con la tua app di sniffare i pacchetti sul traffico verso il tuo server, e quindi di decodificare l'accesso al server con altri tipi di client web. Per questo motivo, Django Rest Framework richiede un CSRF in alcuni casi. Questo è menzionato nel numero Django rest framework documentation.

Il percorso attorno a questo requisito per i POST è di non utilizzare l'autenticazione di sessione. Ad esempio, è possibile utilizzare BasicAuthentication su HTTPS. Con questo meccanismo di autenticazione, è necessario utilizzare HTTPS per impedire che le credenziali vengano passate in chiaro ad ogni richiesta.

+0

> la nostra app dallo sniffare i pacchetti sul traffico - https, quindi no non è questo il motivo. – user3467349

+0

Se stai bene con il rischio di disabilitare CSRF perché non ritieni che i tuoi pacchetti siano insicuri E non c'è alcun browser coinvolto, dovresti provare la soluzione da @Rahul Gupta-Iwasaki –

11

Se qualcuno sta ancora seguendo questa domanda, la risposta diretta è che è necessario utilizzare il decoratore sul metodo di visualizzazione stesso. I metodi get e post definiti nella classe APIView indicano semplicemente a DRF come dovrebbe comportarsi la visualizzazione effettiva, ma il metodo di visualizzazione previsto dal router django non viene effettivamente istanziato finché non si chiama LoginView.as_view().

Pertanto, la soluzione è aggiungere csrf_exempt decoratore a urls.py. Potrebbe apparire come segue:

#file: urls.py 

from django.conf.urls import patterns, url 
from django.views.decorators.csrf import csrf_exempt 

import views 

urlpatterns = patterns('', 
    url('^login/$', csrf_exempt(views.LoginView.as_view())), 
    ... 
) 

Tuttavia, come sottolinea Mark sopra, la protezione CSRF è importante per evitare che le sessioni di essere dirottato. Non ho mai lavorato con iOS, ma vorrei esaminare l'uso di django cookie-based csrf tokens. Puoi utilizzare il decoratore ensure_csrf_cookie per fare in modo che django invii un cookie csrftoken con una risposta e le tue richieste POST verranno convalidate fintanto che includi quel token come intestazione X-CSRFToken.

0

Questa è una vecchia domanda ma qualcosa che abbiamo incontrato di recente.

DRF disattiva CSRF per impostazione predefinita, a meno che non si usi l'autenticazione di sessione. Per impostazione predefinita, NSURLconnection è impostato per gestire i cookie. Devi dire esplicitamente all'app iOS di non utilizzare i cookie. Quindi è possibile continuare a utilizzare l'autenticazione di sessione, se necessario, e non dovere esonerare csrf dalle proprie visualizzazioni.

1

Il problema si verifica qui è che Django per l'elaborazione della tua vista sta usando qualsiasi metodo as_view() tornerà, non direttamente il metodo get() o post().

Pertanto si dovrebbe decorare la vostra vista di classe sede in uno dei seguenti modi:

  1. negli URL.py
 
    urlpatterns = patterns('', 
     url('^login/$', csrf_exempt(views.LoginView.as_view())), 
     ... 
    ) 
  1. o dispatch() metodo (pre django 1,9)
 
    from django.utils.decorators import method_decorator 

    class LoginView(APIView): 
     @method_decorator(csrf_exempt) 
     def dispatch(self, *args, **kwargs): 
      ... 
  1. o visualizzazione di classe stessa (da django 1,9)
 
    from django.utils.decorators import method_decorator 


    @method_decorator(csrf_exempt, name='dispatch') 
    class LoginView(APIView): 
      ... 
0

Ho avuto lo stesso problema. Il mio problema era che ho dimenticato di ma .as_view() in urls.py su MyAPIView. Quindi ha bisogno di essere come:

url(r'$', GetLikesAPI.as_view(), name='list') 
non

:

url(r'$', GetLikesAPI, name='list')