CSRF ve API'ler
Coddy'nin Django Journey'sinin JSON API'leri bölümünün bir parçası. Ders 6 / 19.
POST /api/tasks/ gönderen gerçek bir program 403 Forbidden yanıtını alır. Django'nun CSRF koruması, başka bir web sitesinin ziyaretçinin tarayıcısına formlarınızı göndertmesini önlemek için her POST isteğinin kendi sayfalarınızdan birinden alınan gizli bir token taşımasını ister. Bir programın böyle bir sayfası ve token'ı yoktur.
django.views.decorators.csrf içindeki @csrf_exempt, tek bir görünüm için bu denetimi kapatır:
@csrf_exempt
def webhook(request):
...Bunun bir bedeli vardır: artık herhangi bir web sitesi ziyaretçinin tarayıcısına bu POST isteğini göndertilebilir. Görev listesi gibi, oturum açmış kullanıcının kim olduğuna bağlı olmayan bir görünüm için bu sorun değildir. Oturum açmış kullanıcı adına işlem yapan bir API'de CSRF koruması açık kalır ve sayfanın betiği token'ı X-CSRFToken başlığında gönderir.
Görev
OrtaCSRF belirteci olmayan programların görev oluşturmasına izin ver. tasks/views.py içinde denetimden yalnızca task_list işlevini muaf tut; böylece POST /api/tasks/ belirteç olmadan çalışır.
Aşağıdaki satırı Shell sekmesinde çalıştır; burada enforce_csrf_checks=True, test Client'ının belirteçleri denetlemesini sağlar: 403 yerine 201 yazdırır.
from django.test import Client; print(Client(enforce_csrf_checks=True).post("/api/tasks/", {"title": "Pay rent"}, content_type="application/json").status_code)Kendin dene
import json
from django.http import JsonResponse
from django.shortcuts import render
from .models import Task
def task_to_dict(task):
return {
"id": task.id,
"title": task.title,
"done": task.done,
"priority": task.priority,
}
def home(request):
return render(request, "tasks/home.html", {"tasks": Task.objects.all()})
def stats(request):
data = {
"total": Task.objects.count(),
"done": Task.objects.filter(done=True).count(),
}
return JsonResponse(data)
def task_list(request):
if request.method == "POST":
data = json.loads(request.body)
task = Task.objects.create(
title=data["title"],
priority=data.get("priority", "normal"),
)
return JsonResponse(task_to_dict(task), status=201)
tasks = Task.objects.all()
done = request.GET.get("done")
if done == "true":
tasks = tasks.filter(done=True)
elif done == "false":
tasks = tasks.filter(done=False)
return JsonResponse([task_to_dict(task) for task in tasks], safe=False)
def task_detail(request, pk):
task = Task.objects.filter(pk=pk).first()
if task is None:
return JsonResponse({"error": "Task not found"}, status=404)
return JsonResponse(task_to_dict(task))
JSON API'leri bölümündeki tüm dersler
2İstekleri Okuma
Sorguyla FiltrelemePOST ile OluşturmaKendi başına pratik yap: Django playground