2015-09-18 17 views
5

Sto utilizzando uno django-oneall per consentire l'autenticazione della sessione di accesso social sul mio sito. Sebbene non sia uno dei provider di autenticazione suggeriti per django-rest-framework, rest_framework.authentication.SessionAuthentication utilizza l'autenticazione di sessione predefinita di django. quindi ho pensato che dovrebbe essere abbastanza semplice da integrare.django-rest-framework restituisce la risposta 403 su POST, PUT, DELETE nonostante le autorizzazioni AllowAny

Per quanto riguarda le autorizzazioni, in definitiva userò lo IsAdmin, ma a fini di sviluppo, l'ho appena impostato su IsAuthenticated. Quando ho restituito 403, ho rilasciato le autorizzazioni a AllowAny, ma ancora nessun dado. Ecco il mio riposo config quadro:

settings.py

REST_FRAMEWORK = { 
    'DEFAULT_AUTHENTICATION_CLASSES': (
     'rest_framework.authentication.SessionAuthentication', 
    ), 
    'DEFAULT_PERMISSION_CLASSES': (
     'rest_framework.permissions.AllowAny', 
     # 'rest_framework.permissions.IsAuthenticated', 
     # 'rest_framework.permissions.IsAdminUser', 
    ), 
    'PAGE_SIZE': 100, 
    'DEFAULT_FILTER_BACKENDS': (
     'rest_framework.filters.DjangoFilterBackend', 
    ), 
} 

EDIT:

ho ottenuto questo lavoro basato sulla risposta qui sotto. Risulta che rest_framework si aspetta sia il cookie csrftoken sia un'intestazione X-CSRFToken dello stesso valore, ho impostato il mio codice di front-end per inviare quell'intestazione per tutte le richieste ajax e tutto ha funzionato correttamente.

risposta

13

Django REST quadro restituisce il codice di stato 403 sotto un paio di circostanze rilevanti:.

  • quando non si ha il livello di autorizzazione necessaria (ad esempio facendo una richiesta API come un utente non autenticato quando DEFAULT_PERMISSION_CLASSES è ('rest_framework.permissions.IsAuthenticated',)
  • Quando si fa un tipo di richiesta non sicuro (POST, PUT, patch o DELETE - una richiesta che dovrebbe avere effetti collaterali), che si sta utilizzando rest_framework.authentication.SessionAuthentication e non ho compreso il tuo CSRFToken nel requeset
  • Quando si sta facendo. un pericoloso il tipo di richiesta e il CSRFToken che hai incluso non sono più validi.

Ho intenzione di fare alcune richieste di dimostrazione contro un'API di test per dare un esempio di ciascuna per aiutarti a diagnosticare quale problema stai riscontrando e come risolverlo. Userò la libreria requests.

L'API prova

a impostare un'API molto semplice DRF con un unico modello, Life, che contiene un singolo campo (answer, con un valore predefinito di 42). Tutto da qui in avanti è abbastanza semplice; Ho impostato uno ModelSerializer - LifeSerializer, uno ModelViewSet - LifeViewSet e uno DefaultRouter sulla route URL /life. Ho configurato DRF per richiedere che l'utente sia autenticato per utilizzare l'API e per utilizzare SessionAuthentication.

Colpire l'API

import json 
import requests 

response = requests.get('http://localhost:8000/life/1/') 
# prints (403, '{"detail":"Authentication credentials were not provided."}') 
print response.status_code, response.content 

my_session_id = 'mph3eugf0gh5hyzc8glvrt79r2sd6xu6' 
cookies = {} 
cookies['sessionid'] = my_session_id 
response = requests.get('http://localhost:8000/life/1/', 
         cookies=cookies) 
# prints (200, '{"id":1,"answer":42}') 
print response.status_code, response.content 

data = json.dumps({'answer': 24}) 
headers = {'content-type': 'application/json'} 
response = requests.put('http://localhost:8000/life/1/', 
         data=data, headers=headers, 
         cookies=cookies) 
# prints (403, '{"detail":"CSRF Failed: CSRF cookie not set."}') 
print response.status_code, response.content 

# Let's grab a valid csrftoken 
html_response = requests.get('http://localhost:8000/life/1/', 
          headers={'accept': 'text/html'}, 
          cookies=cookies) 
cookies['csrftoken'] = html_response.cookies['csrftoken'] 
response = requests.put('http://localhost:8000/life/1/', 
         data=data, headers=headers, 
         cookies=cookies) 
# prints (403, '{"detail":"CSRF Failed: CSRF token missing or incorrect."}') 
print response.status_code, response.content 

headers['X-CSRFToken'] = cookies['csrftoken'] 
response = requests.put('http://localhost:8000/life/1/', 
         data=data, headers=headers, 
         cookies=cookies) 
# prints (200, '{"id":1,"answer":24}') 
print response.status_code, response.content 
+0

hmm ... il mio Ember app è infatti passa il cookie CSRF nella richiesta. Ho una configurazione proxy inverso in apache per il mio riposo API. Forse ho bisogno di modificare in qualche modo il mio proxy inverso in modo che copi il valore del cookie csrf nell'intestazione 'HTTP_X_CSRFTOKEN'? – ckot

+0

Credo che dovrei piuttosto configurare ember per passare sempre il valore del cookie csrftoken nell'intestazione. dovrebbe essere più facile – ckot

+1

@ckot Ho aggiornato la mia risposta. Hai dimenticato che l'intestazione 'X-CSRFToken' e il cookie' csrftoken' dovevano essere impostati. – chucksmash