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 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ınmış gizli bir belirteç taşımasını ister. Bir programın böyle bir sayfası ve belirteci yoktur.
django.views.decorators.csrf içindeki @csrf_exempt, bir görünüm için denetimi devre dışı bırakı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ış kişinin kim olduğuna bağlı olmayan bir görünüm için uygundur. Oturum açmış kullanıcı adına işlem yapan bir API, CSRF korumasını açık tutar ve sayfasındaki betik belirteci bir X-CSRFToken başlığında gönderir.
Görev
OrtaCSRF belirteci olmadan programların görev oluşturmasına izin ver:
POST /api/tasks/belirteç olmadan çalışır.- Yalnızca
task_listmuaf tutulur.
Çalıştır'a bas, ardından Kabuk sekmesine şunu yaz. Değişiklikten önce 403, değişiklikten sonra 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