webentwicklung-frage-antwort-db.com.de

Wie erstelle ich einen POST einfachen JSON mit Django REST Framework? CSRF-Token fehlt oder ist falsch?

Würde mich über jemanden freuen, der mir zeigt, wie man eine einfache POST Anfrage mit JSON mit Django REST Framework erstellt. Ich verstehe nicht Irgendwelche Beispiele dafür im Tutorial?

Hier ist mein Rollenmodellobjekt, das ich POSTEN möchte. Dies ist eine brandneue Rolle, die ich der Datenbank hinzufügen möchte, aber es wird ein Fehler von 500 angezeigt.

{
    "name": "Manager", 
    "description": "someone who manages"
}

Hier ist meine Curl-Anfrage an einem Bash-Terminal Prompt:

curl -X POST -H "Content-Type: application/json" -d '[
{
    "name": "Manager", 
    "description": "someone who manages"
}]'


http://localhost:8000/lakesShoreProperties/role

Die URL

http://localhost:8000/lakesShoreProperties/roles

Funktioniert mit einer GET-Anforderung, und ich kann alle Rollen in der Datenbank abrufen, aber scheinbar keine neuen Rollen erstellen. Ich habe keine Berechtigungen festgelegt. Ich verwende eine Standardansicht in views.py

class RoleDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Role.objects.all()
    serializer_class = RoleSerializer
    format = None

class RoleList(generics.ListCreateAPIView): 
        queryset = Role.objects.all()
        serializer_class = RoleSerializer
        format = None

Und in meinem urls.py Für diese App sind die relevanten URL-Ansichtszuordnungen korrekt:

url(r'^roles/$', views.RoleList.as_view()),
url(r'^role/(?P<pk>[0-9]+)/$', views.RoleDetail.as_view()),

Fehlermeldung ist:

{
    "detail": "CSRF Failed: CSRF token missing or incorrect."
}

Was ist hier los und was ist die Lösung dafür? Ist localhost eine standortübergreifende Anfrage? Ich habe hinzugefügt @csrf_exempt zu RoleDetail und RoleList, aber es scheint nichts zu ändern. Kann dieser Decorator überhaupt zu einer Klasse hinzugefügt werden oder muss er zu einer Methode hinzugefügt werden? Hinzufügen des @csrf_exempt dekorieren, mein Fehler wird:

Request Method: POST
Request URL:    http://127.0.0.1:8000/lakeshoreProperties/roles/
Django Version: 1.5.1
Exception Type: AttributeError
Exception Value:    
'function' object has no attribute 'as_view'

Dann habe ich CSRF in der gesamten App deaktiviert und erhalte jetzt die folgende Meldung:

{"non_field_errors": ["Invalid data"]} Wenn mein mir bekanntes JSON-Objekt ein gültiger JSON ist. Es ist ein Nichtfeldfehler, aber ich stecke hier fest.

Nun, es stellt sich heraus, dass mein json nicht gültig war?

{
    "name": "admin", 
    "description": "someone who administrates"
}

vs

[
    {
        "name": "admin",
        "description": "someone who administrates"
    }
]

Wenn die umschließenden Klammern [] verwendet werden, schlägt die Anforderung POST) fehl. Mit dem Validator von jsonlint.com werden jedoch beide meiner json-Objekte validiert.

Update : Das Problem bestand beim Versenden des POST mit PostMan, nicht im Backend. Siehe https : //stackoverflow.com/a/17508420/203312

44
user798719

Wahrscheinlich müssen Sie das CSRF-Token zusammen mit Ihrer Anfrage senden. Check out https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/#csrf-ajax

Update: Da Sie bereits versucht haben, CSRF auszuschließen, könnte dies möglicherweise helfen (abhängig von der verwendeten Version von Django)): https://stackoverflow.com/a/14379073/977931

10
stellarchariot

CSRF ist in Django REST Framework standardmäßig ausgenommen. Daher funktioniert curl POST request einwandfrei. Der POSTMAN-Aufruf hat CSRF zurückgegeben Falsch, da POSTMAN das csrf-Token enthält, wenn es in Cookies gefunden wird. Sie können dies beheben, indem Sie Cookies bereinigen.

34
Terry Lam

Es ist aus Ihren REST Framework-Einstellungen. In Ihrem settings.py Datei, Ihr REST_FRAMEWORK sollte folgendes haben.

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),
   'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.AllowAny',
    ),
}

Dies legt fest, dass Ihr REST Framework die Tokenauthentifizierung anstelle der csrf-Authentifizierung verwendet. Wenn Sie die Berechtigung auf AllowAny setzen, können Sie sich nur dort authentifizieren, wo Sie möchten.

24
pharingee

OK, jetzt nehme ich natürlich zurück, was ich gesagt habe. CSRF funktioniert wie vorgesehen.

Ich habe eine POST Anfrage mit einem chrome Plugin namens POSTMAN gestellt. Meine POST Anfrage schlägt mit aktiviertem CSRF fehl.

Aber eine Locke POST Anfrage mit

curl -X POST -H "Content-Type: application/json" -d '
{
    "name": "Manager",
    "description": "someone who manages"
}' http://127.0.0.1:8000/lakeshoreProperties/roles/

funktioniert einwandfrei ... Ich musste die geschweiften Klammern entfernen, d. h. [], und sicherstellen, dass in Rollen ein Schrägstrich nach dem 's' steht, d. h. Rollen/und csrf aktiviert haben keine Fehler ausgegeben.

Ich bin nicht sicher, was der Unterschied zwischen dem Aufrufen mit POSTMAN und dem Verwenden von Curl ist, aber POSTMAN wird im Webbrowser ausgeführt, was den größten Unterschied darstellt. Das heißt, ich habe csrf für die gesamte Klasse RoleList deaktiviert, aber eine identische Anforderung funktioniert mit Curl, schlägt jedoch mit POSTMAN fehl.

10
user798719

So informieren Sie sich über den aktuellen Status und fassen einige Antworten zusammen:

AJAX-Anforderungen, die im selben Kontext wie die API gestellt werden, mit der sie interagieren, verwenden normalerweise SessionAuthentication. Dadurch wird sichergestellt, dass nach dem Anmelden eines Benutzers alle gestellten AJAX) - Anforderungen mit derselben sitzungsbasierten Authentifizierung authentifiziert werden können, die für den Rest der Website verwendet wird.

AJAX-Anforderungen, die auf einer anderen Site als der API gestellt werden, mit der sie kommunizieren, müssen in der Regel ein nicht sitzungsbasiertes Authentifizierungsschema verwenden, z. B. TokenAuthentication.

Daher können Antworten, die empfehlen, SessionAuthentication durch TokenAuthentication zu ersetzen, das Problem lösen, sind jedoch nicht unbedingt vollständig korrekt.

Um sich gegen diese Art von Angriffen zu schützen, müssen Sie zwei Dinge tun:

  1. Stellen Sie sicher, dass die "sicheren" HTTP-Vorgänge wie GET, HEAD und OPTIONS nicht zum Ändern des serverseitigen Status verwendet werden können.

  2. Stellen Sie sicher, dass für 'unsichere' HTTP-Vorgänge wie POST, PUT, PATCH und DELETE immer ein gültiges CSRF-Token erforderlich ist. Wenn Sie SessionAuthentication verwenden, müssen Sie gültige CSRF-Token für alle POST-, PUT-, PATCH- oder DELETE -Operationen einschließen .

Um AJAX) -Anfragen zu stellen, müssen Sie das CSRF-Token in den HTTP-Header aufnehmen, wie in = beschrieben Django Dokumentation.

Daher ist es wichtig, dass csrf im Header enthalten ist, wie zum Beispiel diese Antwort nahelegt.

Referenz: Arbeiten mit AJAX, CSRF & CORS, Django REST Framework-Dokumentation .

4
Wtower

Wie Sie sagten, war Ihre URL

http://localhost:8000/lakesShoreProperties/roles

Postbote hat einige Probleme mit localhost. Senden der POST an 127.0.0.1:8000/your-api/endpoint hat stattdessen den Trick für mich getan.

3
Thosse

das alte Postman hat ein Problem mit CSRF-Token, da es nicht mit Cookies funktioniert.

Ich schlage vor, dass Sie auf die neue Version von Postbote umsteigen, da diese mit Cookies funktioniert und Sie dieses Problem nicht mehr haben.

1

wenn Sie die Berechtigung AllowAny festgelegt haben und mit einem CSRF-Problem konfrontiert sind

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.AllowAny'
    ]
}

dann setzen folgende in die settings.py wird das Problem beheben

REST_SESSION_LOGIN = False
0
navyad