Ulaşım
- Adres:Batıkent Mh. 8910 Sk. 6. Etap 1H No: 18 Yeni Toki Eyyübiye / Şanlıurfa (Yeni Alım Satım Karşısı)
- Telefon:0 (545) 528 88 93
- eMail: info@alestaweb.com
Web geliştiricilerin sıkça karşılaştığı Django CSRF Token Hatası (CSRF Token Missing Error), form gönderimlerinde güvenlik katmanı olan Cross-Site Request Forgery korumasından kaynaklanır. Alesta Web olarak bu hatanın nedenlerini, çözümlerini ve Django güvenlik best practices'i detaylı şekilde anlatalım.
Cross-Site Request Forgery (CSRF), kötü niyetli sitelerin kullanıcı adına yetkisiz işlemler yapmasını engelleyen bir güvenlik mekanizmasıdır. Django framework'ü varsayılan olarak tüm POST isteklerinde CSRF Token kontrolü yapar.
| Adım | Açıklama |
|---|---|
| 1. Token Oluşturma | Django her session için benzersiz token üretir |
| 2. Template'e Gömme | {% csrf_token %} tag ile form'a hidden input eklenir |
| 3. Cookie Gönderme | csrftoken cookie'si tarayıcıya kaydedilir |
| 4. Doğrulama | POST isteğinde token ile cookie eşleştirilir |
OWASP 2025 raporuna göre CSRF saldırıları web uygulamalarındaki güvenlik açıklarının %8'ini oluşturuyor. Django'nun otomatik CSRF koruması bu riski minimize eder.
Django CSRF Token Hatası genellikle şu senaryolarda ortaya çıkar:
# Hata 1: Template'de token eksik
Forbidden (403)
CSRF verification failed. Request aborted.
Reason given for failure:
CSRF token missing or incorrect.
# Hata 2: AJAX'ta header eksik
403 Forbidden - CSRF token missing
# Hata 3: Middleware devre dışı
ImproperlyConfigured: CSRF middleware not installed
Alesta Web müşterilerimizin %30'u Django projelerinde bu hatayla karşılaşıyor. En yaygın nedenler:
{% csrf_token %} tag'inin unutulmasıX-CSRFToken header'ının eksik olmasıEn yaygın Django CSRF Token Hatası çözümü, form template'ine doğru tag'i eklemektir:
<!-- templates/contact.html -->
<form method="post" action="/contact/">
<input type="text" name="name" placeholder="Adınız">
<input type="email" name="email" placeholder="Email">
<button type="submit">Gönder</button>
</form>
<!-- templates/contact.html -->
<form method="post" action="/contact/">
{% csrf_token %}
<input type="text" name="name" placeholder="Adınız">
<input type="email" name="email" placeholder="Email">
<button type="submit">Gönder</button>
</form>
Django otomatik olarak şu HTML'i oluşturur:
<input type="hidden" name="csrfmiddlewaretoken"
value="xK3l9mP2...64karakterlik_token">
{% csrf_token %} tag'i mutlaka <form> tag'lerinin içinde olmalıdır. Dışarıda kullanırsanız token oluşturulur ama form ile gönderilmez.
JavaScript ile AJAX kullanıyorsanız, CSRF Token Missing hatası almamak için HTTP header'a token eklemelisiniz:
// Cookie'den CSRF token'ı al
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
const csrftoken = getCookie('csrftoken');
// Fetch ile POST isteği
fetch('/api/submit/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
body: JSON.stringify({ name: 'Test', email: 'test@example.com' })
})
.then(response => response.json())
.then(data => console.log('Başarılı:', data))
.catch(error => console.error('Hata:', error));
// jQuery ile CSRF token ayarlama
function csrfSafeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});
// Artık tüm AJAX istekleri otomatik token gönderir
$.post('/api/submit/', {
name: 'Test',
email: 'test@example.com'
}, function(data) {
console.log('Başarılı:', data);
});
Alesta Web projelerinde React ve Vue.js kullanıyorsak, axios interceptor ile global CSRF token ayarı yapıyoruz:
// axios-config.js
import axios from 'axios';
// CSRF token'ı cookie'den al
const csrftoken = document.cookie
.split('; ')
.find(row => row.startsWith('csrftoken='))
?.split('=')[1];
// Tüm isteklere otomatik ekle
axios.defaults.headers.common['X-CSRFToken'] = csrftoken;
axios.defaults.withCredentials = true;
export default axios;
API endpoint'leri veya webhook'lar için Django CSRF Token Hatası kontrolünü devre dışı bırakabilirsiniz (dikkatli kullanın):
# views.py
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
import json
@csrf_exempt
def webhook_endpoint(request):
"""
Dış servislerden gelen webhook'lar için CSRF kontrolü devre dışı
ÖNEMLİ: Sadece güvenli authentication mekanizması olan endpoint'lerde kullanın
"""
if request.method == 'POST':
try:
data = json.loads(request.body)
# Webhook işleme mantığı
return JsonResponse({'status': 'success', 'message': 'Webhook alındı'})
except json.JSONDecodeError:
return JsonResponse({'status': 'error', 'message': 'Geçersiz JSON'}, status=400)
return JsonResponse({'status': 'error', 'message': 'Sadece POST'}, status=405)
# views.py
from django.views import View
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
@method_decorator(csrf_exempt, name='dispatch')
class StripeWebhookView(View):
"""
Stripe webhook'ları için CSRF bypass
Stripe signature doğrulaması yapıyor, CSRF'ye gerek yok
"""
def post(self, request):
payload = request.body
sig_header = request.META['HTTP_STRIPE_SIGNATURE']
# Stripe signature doğrulama
# ... (webhook işleme kodu)
return JsonResponse({'status': 'success'})
@csrf_exempt kullandığınızda CSRF koruması tamamen kalkar. Mutlaka alternatif güvenlik mekanizmaları kullanın:
CSRF Token Missing hatası alıyorsanız, middleware ayarlarınızı kontrol edin:
# settings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', # ✅ MUTLAKA OLMALI
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# CSRF Cookie Ayarları
CSRF_COOKIE_SECURE = True # Production'da HTTPS için
CSRF_COOKIE_HTTPONLY = False # JavaScript'in cookie'ye erişmesi için False
CSRF_COOKIE_SAMESITE = 'Lax' # Veya 'Strict' (third-party cookie engeller)
CSRF_TRUSTED_ORIGINS = [
'https://yourdomain.com',
'https://www.yourdomain.com',
]
# Django shell'de middleware kontrolü
python manage.py shell
>>> from django.conf import settings
>>> 'django.middleware.csrf.CsrfViewMiddleware' in settings.MIDDLEWARE
True # ✅ Bu True olmalı
Modern tarayıcılar (Chrome 80+, Firefox 69+) SameSite cookie politikası nedeniyle Django CSRF Token Hatası verebilir:
| Ayar | Davranış | Kullanım Durumu |
|---|---|---|
| Strict | Cookie sadece same-site isteklerde gönderilir | Maksimum güvenlik, tek domain |
| Lax | Top-level navigation'da (link tıklama) gönderilir | Önerilen (Django default) |
| None | Tüm cross-site isteklerde gönderilir | HTTPS + third-party iframes |
# settings.py - Production ortamı için
import os
# CSRF Ayarları
CSRF_COOKIE_SECURE = True # HTTPS zorunlu
CSRF_COOKIE_SAMESITE = 'Lax' # Çoğu use case için yeterli
CSRF_USE_SESSIONS = False # Cookie kullan (default)
# Session Ayarları
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE = 'Lax'
# Güvenilen domainler
CSRF_TRUSTED_ORIGINS = [
'https://alestaweb.com',
'https://www.alestaweb.com',
'https://api.alestaweb.com',
]
# HTTPS redirect
SECURE_SSL_REDIRECT = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
Subdomain'ler arasında CSRF token paylaşımı yapıyorsanız (örn: app.alestaweb.com → api.alestaweb.com), CSRF_COOKIE_DOMAIN ayarını kullanın:
CSRF_COOKIE_DOMAIN = '.alestaweb.com' # Tüm subdomain'lerde geçerli
Alesta Web olarak production ortamlarında Django CSRF Token Hatası önlemek için şu pratikleri uyguluyoruz:
# /etc/nginx/sites-available/django-app
server {
listen 443 ssl http2;
server_name alestaweb.com;
# SSL Sertifikaları
ssl_certificate /etc/letsencrypt/live/alestaweb.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/alestaweb.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; # ✅ HTTPS için önemli
# CSRF cookie'lerinin düzgün iletilmesi
proxy_cookie_path / "/; Secure; HttpOnly; SameSite=Lax";
}
}
# docker-compose.yml
version: '3.8'
services:
web:
build: .
command: gunicorn config.wsgi:application --bind 0.0.0.0:8000
volumes:
- .:/app
environment:
- DJANGO_SETTINGS_MODULE=config.settings.production
- CSRF_COOKIE_SECURE=True
- SESSION_COOKIE_SECURE=True
- CSRF_TRUSTED_ORIGINS=https://alestaweb.com,https://www.alestaweb.com
ports:
- "8000:8000"
depends_on:
- db
db:
image: postgres:15
environment:
- POSTGRES_DB=django_db
- POSTGRES_USER=django_user
- POSTGRES_PASSWORD=secure_password
# settings.py - CSRF hatalarını loglama
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'file': {
'level': 'WARNING',
'class': 'logging.FileHandler',
'filename': '/var/log/django/csrf_errors.log',
},
},
'loggers': {
'django.security.csrf': {
'handlers': ['file'],
'level': 'WARNING',
'propagate': False,
},
},
}
CSRF Token Missing hatasını çözerken güvenliği asla ihmal etmeyin:
Alesta Web support ekibimizin gözlemlediği en yaygın hatalar:
Django CSRF Token Hatası genellikle template'e {% csrf_token %} eklenmemesi veya AJAX'ta X-CSRFToken header eksikliğinden kaynaklanır. CSRF Token Missing sorununu çözerken güvenliği ihmal etmeyin.
Hızlı Kontrol Listesi:
Faydalı Kaynaklar:
© 2026 Alesta Web - Django güvenlik ve performans uzmanınız. Tüm hakları saklıdır.