Menu
CoddyTech

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.

challenge icon

Görev

Orta

CSRF belirteci olmadan programların görev oluşturmasına izin ver:

  • POST /api/tasks/ belirteç olmadan çalışır.
  • Yalnızca task_list muaf 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

Kendi başına pratik yap: Django playground