CSRF dan API
Termasuk bagian API JSON dalam perjalanan Django di Coddy. Pelajaran 6 dari 19.
Program sungguhan yang mengirim POST /api/tasks/ mendapat 403 Forbidden. Perlindungan CSRF Django mengharuskan setiap POST membawa token rahasia dari salah satu halaman milikmu, agar situs web lain tidak dapat membuat browser pengunjung mengirim formulirmu. Program tidak memiliki halaman dan token seperti itu.
@csrf_exempt, dari django.views.decorators.csrf, menonaktifkan pemeriksaan untuk satu view:
@csrf_exempt
def webhook(request):
...Namun, ada konsekuensinya: situs web mana pun kini dapat membuat browser pengunjung mengirim POST ini. Ini tidak masalah untuk view yang tidak bergantung pada siapa yang sedang login, seperti daftar task. API yang bertindak sebagai pengguna yang sedang login tetap mengaktifkan CSRF, dan skrip di halamannya mengirim token di header X-CSRFToken.
Tantangan
SedangIzinkan program tanpa token CSRF membuat tugas:
POST /api/tasks/berfungsi tanpa token.- Hanya
task_listyang dikecualikan.
Tekan Jalankan, lalu ketik ini di tab Shell. Sebelum perubahan, hasilnya 403, setelahnya 201: from django.test import Client; print(Client(enforce_csrf_checks=True).post("/api/tasks/", {"title": "Pay rent"}, content_type="application/json").status_code)
Coba sendiri
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))
Semua pelajaran di API JSON
2Membaca Permintaan
Memfilter dengan QueryMembuat dengan POST5Proyek: Mengurutkan Pekerjaan
Proyek: PrioritasProyek: Menghapus Tugas yang SelesaiLatihan sendiri: Playground Django