Communitygithub.com

django-security

Bewährte Sicherheitspraktiken für Django: Authentifizierung, Autorisierung, CSRF-Schutz, SQL-Injection-Prävention, XSS-Schutz und sichere Deployment-Konfigurationen. Verwenden Sie dies bei der Überprüfung von Django-Authentifizierung, -Autorisierung, -Eingabeverarbeitung oder -Bereitstellungseinstellungen.

Was ist django-security?

Diese Skill-Anleitung bietet umfassende Sicherheitsrichtlinien für Django-Anwendungen, um gängige Sicherheitslücken zu schließen. Sie behandelt kritische Bereiche wie Authentifizierung (einschließlich benutzerdefinierter Benutzermodelle und sicherer Passwort-Hashing mit Argon2), Autorisierung mit rollenbasiertem Zugriff (RBAC) und detaillierten Berechtigungen, sowie CSRF-Schutz mit gesicherten Cookies und SameSite-Richtlinien. Die Anleitung demonstriert die Prävention von SQL-Injection durch die Verwendung von Django ORM und parametrisierten Abfragen, XSS-Schutz durch Template-Escaping und HTTP-Header wie Content-Security-Policy, sowie die Validierung von Datei-Uploads mit Magic-Bytes und Python-Bibliotheken wie `python-magic` oder `filetype`. Sie unterstützt die Plattformen Django und Django REST Framework und enthält Produktionskonfigurationen für HSTS-Sicherheitsheader, sichere Sitzungsverwaltung und Ratenbegrenzung. Entwickler können diese Richtlinien direkt in ihre Projekte integrieren, indem sie die bereitgestellten Codeblöcke als Vorlage für ihre `settings.py`, Modelle und Views verwenden. Die Skill-Anleitung ist so konzipiert, dass sie in den KI-Assistenten Claude Code, Cursor, Codex und andere ähnliche Tools integriert werden kann. Sie wird aktiviert, wenn der Entwickler Django-Authentifizierung, -Autorisierung, Eingabeverarbeitung oder Bereitstellungseinstellungen einrichtet oder überprüft. Der Fokus liegt auf der praktischen Umsetzung von Sicherheitsmaßnahmen, die einfach zu implementieren und zu verstehen sind.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/django-security

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Best Practices für Django-Sicherheit

Umfassende Sicherheitsrichtlinien für Django-Anwendungen zum Schutz vor häufigen Schwachstellen.

Wann zu aktivieren

  • Einrichten von Django-Authentifizierung und -Autorisierung
  • Implementieren von Benutzerberechtigungen und -rollen
  • Konfigurieren von Produktionssicherheitseinstellungen
  • Überprüfen einer Django-Anwendung auf Sicherheitsprobleme
  • Bereitstellen von Django-Anwendungen in der Produktion

Zentrale Sicherheitseinstellungen

Produktionseinstellungen konfigurieren

# settings/production.py
import os

DEBUG = False  # KRITISCH: Niemals True in der Produktion verwenden

ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '').split(',')

# Sicherheitsheader
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = 31536000  # 1 Jahr
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_BROWSER_XSS_FILTER = True
X_FRAME_OPTIONS = 'DENY'

# HTTPS und Cookies
SESSION_COOKIE_HTTPONLY = True
CSRF_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Lax'
CSRF_COOKIE_SAMESITE = 'Lax'

# Geheimer Schlüssel (muss über Umgebungsvariable gesetzt werden)
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')
if not SECRET_KEY:
    raise ImproperlyConfigured('Die Umgebungsvariable DJANGO_SECRET_KEY ist erforderlich')

# Passwortvalidierung
AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
        'OPTIONS': {
            'min_length': 12,
        }
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

Authentifizierung

Benutzerdefiniertes Benutzermodell

# apps/users/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models

class User(AbstractUser):
    """Benutzerdefiniertes Benutzermodell für bessere Sicherheit."""

    email = models.EmailField(unique=True)
    phone = models.CharField(max_length=20, blank=True)

    USERNAME_FIELD = 'email'  # E-Mail als Benutzername verwenden
    REQUIRED_FIELDS = ['username']

    class Meta:
        db_table = 'users'
        verbose_name = 'Benutzer'
        verbose_name_plural = 'Benutzer'

    def __str__(self):
        return self.email

# settings/base.py
AUTH_USER_MODEL = 'users.User'

Passwort-Hashing

# Django verwendet standardmäßig PBKDF2. Für stärkere Sicherheit:
PASSWORD_HASHERS = [
    'django.contrib.auth.hashers.Argon2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
    'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
]

Sitzungsverwaltung

# Sitzungskonfiguration
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # Oder 'db'
SESSION_CACHE_ALIAS = 'default'
SESSION_COOKIE_AGE = 3600 * 24 * 7  # 1 Woche
SESSION_SAVE_EVERY_REQUEST = False
SESSION_EXPIRE_AT_BROWSER_CLOSE = False  # Bessere Benutzererfahrung, aber weniger sicher

Autorisierung

Berechtigungen

# models.py
from django.db import models
from django.contrib.auth.models import Permission

class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)

    class Meta:
        permissions = [
            ('can_publish', 'Kann Beiträge veröffentlichen'),
            ('can_edit_others', 'Kann Beiträge anderer bearbeiten'),
        ]

    def user_can_edit(self, user):
        """Überprüfen, ob ein Benutzer diesen Beitrag bearbeiten kann."""
        return self.author == user or user.has_perm('app.can_edit_others')

# views.py
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.views.generic import UpdateView

class PostUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
    model = Post
    permission_required = 'app.can_edit_others'
    raise_exception = True  # 403 statt Weiterleitung zurückgeben

    def get_queryset(self):
        """Nur Benutzern erlauben, ihre eigenen Beiträge zu bearbeiten."""
        return Post.objects.filter(author=self.request.user)

Benutzerdefinierte Berechtigungen

# permissions.py
from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):
    """Nur Besitzern erlauben, Objekte zu bearbeiten."""

    def has_object_permission(self, request, view, obj):
        # Leseberechtigungen sind für jede Anfrage erlaubt
        if request.method in permissions.SAFE_METHODS:
            return True

        # Schreibberechtigungen nur für den Besitzer
        return obj.author == request.user

class IsAdminOrReadOnly(permissions.BasePermission):
    """Admins dürfen alles, andere nur lesen."""

    def has_permission(self, request, view):
        if request.method in permissions.SAFE_METHODS:
            return True
        return request.user and request.user.is_staff

class IsVerifiedUser(permissions.BasePermission):
    """Nur verifizierten Benutzern erlauben."""

    def has_permission(self, request, view):
        return request.user and request.user.is_authenticated and request.user.is_verified

Rollenbasierte Zugriffskontrolle (RBAC)

# models.py
from django.contrib.auth.models import AbstractUser, Group

class User(AbstractUser):
    ROLE_CHOICES = [
        ('admin', 'Administrator'),
        ('moderator', 'Moderator'),
        ('user', 'Regulärer Benutzer'),
    ]
    role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='user')

    def is_admin(self):
        return self.role == 'admin' or self.is_superuser

    def is_moderator(self):
        return self.role in ['admin', 'moderator']

# Mixins
class AdminRequiredMixin:
    """Mixin, um die Admin-Rolle zu erfordern."""

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_authenticated or not request.user.is_admin():
            from django.core.exceptions import PermissionDenied
            raise PermissionDenied
        return super().dispatch(request, *args, **kwargs)

SQL-Injection-Prävention

Django ORM-Schutz

# GUT: Django ORM maskiert Parameter automatisch
def get_user(username):
    return User.objects.get(username=username)  # Sicher

# GUT: Verwendung von Parametern mit raw()
def search_users(query):
    return User.objects.raw('SELECT * FROM users WHERE username = %s', [query])

# SCHLECHT: Niemals Benutzereingaben direkt interpolieren
def get_user_bad(username):
    return User.objects.raw(f'SELECT * FROM users WHERE username = {username}')  # ANGREIFBAR!

# GUT: Verwendung von filter mit ordnungsgemäßer Maskierung
def get_users_by_email(email):
    return User.objects.filter(email__iexact=email)  # Sicher

# GUT: Verwendung von Q-Objekten für komplexe Abfragen
from django.db.models import Q
def search_users_complex(query):
    return User.objects.filter(
        Q(username__icontains=query) |
        Q(email__icontains=query)
    )  # Sicher

Zusätzliche Sicherheit mit raw()

# Wenn Sie raw SQL verwenden müssen, verwenden Sie immer Parameter
User.objects.raw(
    'SELECT * FROM users WHERE email = %s AND status = %s',
    [user_input_email, status]
)

XSS-Prävention

Template-Maskierung

{# Django maskiert Variablen standardmäßig automatisch - SICHER #}
{{ user_input }}  {# Maskiertes HTML #}

{# Explizit als sicher markieren nur für vertrauenswürdige Inhalte #}
{{ trusted_html|safe }}  {# Nicht maskiert #}

{# Template-Filter für sicheres HTML verwenden #}
{{ user_input|escape }}  {# Wie Standard #}
{{ user_input|striptags }}  {# Alle HTML-Tags entfernen #}

{# JavaScript-Maskierung #}
<script>
    var username = {{ username|escapejs }};
</script>

Sichere String-Behandlung

from django.utils.safestring import mark_safe
from django.utils.html import escape

# SCHLECHT: Niemals Benutzereingaben ohne Maskierung als sicher markieren
def render_bad(user_input):
    return mark_safe(user_input)  # ANGREIFBAR!

# GUT: Zuerst maskieren, dann als sicher markieren
def render_good(user_input):
    return mark_safe(escape(user_input))

# GUT: format_html für HTML mit Variablen verwenden
from django.utils.html import format_html

def greet_user(username):
    return format_html('<span class="user">{}</span>', escape(username))

HTTP-Header

# settings.py
SECURE_CONTENT_TYPE_NOSNIFF = True  # MIME-Sniffing verhindern
SECURE_BROWSER_XSS_FILTER = True  # XSS-Filter aktivieren
X_FRAME_OPTIONS = 'DENY'  # Clickjacking verhindern

# Benutzerdefinierte Middleware
from django.conf import settings

class SecurityHeaderMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        response['X-Content-Type-Options'] = 'nosniff'
        response['X-Frame-Options'] = 'DENY'
        response['X-XSS-Protection'] = '1; mode=block'
        response['Content-Security-Policy'] = "default-src 'self'"
        return response

CSRF-Schutz

Standard-CSRF-Schutz

# settings.py - CSRF ist standardmäßig aktiviert
CSRF_COOKIE_SECURE = True  # Nur über HTTPS senden
CSRF_COOKIE_HTTPONLY = True  # JavaScript-Zugriff verhindern
CSRF_COOKIE_SAMESITE = 'Lax'  # CSRF in einigen Fällen verhindern
CSRF_TRUSTED_ORIGINS = ['https://example.com']  # Vertrauenswürdige Domains

# Template-Verwendung
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Absenden</button>
</form>

# AJAX-Anfragen
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;
}

fetch('/api/endpoint/', {
    method: 'POST',
    headers: {
        'X-CSRFToken': getCookie('csrftoken'),
        'Content-Type': 'application/json',
    },
    body: JSON.stringify(data)
});

Ansichten ausnehmen (Vorsichtig verwenden)

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt  # Nur verwenden, wenn unbedingt nötig!
def webhook_view(request):
    # Webhook von einem externen Dienst
    pass

Sicherheit beim Datei-Upload

Dateivalidierung

import os
import magic  # pip install python-magic
from django.core.exceptions import ValidationError

ALLOWED_MIMES = {
    'image/jpeg', 'image/png', 'image/gif', 'application/pdf',
}

MIME_TO_EXTENSIONS = {
    'image/jpeg': {'.jpg', '.jpeg'},
    'image/png': {'.png'},
    'image/gif': {'.gif'},
    'application/pdf': {'.pdf'},
}

def validate_file_type(value):
    """Dateityp mit Magic-Bytes validieren und Erweiterung gegenprüfen."""
    mime = magic.from_buffer(value.read(2048), mime=True)
    value.seek(0)

    if mime not in ALLOWED_MIMES:
        raise ValidationError('Nicht unterstützter Dateityp.')

    ext = os.path.splitext(value.name)[1].lower()
    if ext not in MIME_TO_EXTENSIONS.get(mime, set()):
        raise ValidationError('Dateierweiterung stimmt nicht mit Dateiinhalt überein.')

def validate_file_size(value):
    """Dateigröße validieren (max. 5 MB)."""
    if value.size > 5 * 1024 * 1024:
        raise ValidationError('Datei zu groß. Maximalgröße beträgt 5 MB.')

# models.py
class Document(models.Model):
    file = models.FileField(
        upload_to='documents/',
        validators=[validate_file_type, validate_file_size]
    )

Für Umgebungen, in denen die Installation von libmagic schwierig ist (z. B. minimale Container), verwenden Sie als Alternative das reine Python-Paket filetype:

import os
from django.core.exceptions import ValidationError

import filetype  # pip install filetype

ALLOWED_MIMES = {
    'image/jpeg', 'image/png', 'image/gif', 'application/pdf',
}

MIME_TO_EXTENSIONS = {
    'image/jpeg': {'.jpg', '.jpeg'},
    'image/png': {'.png'},
    'image/gif': {'.gif'},
    'application/pdf': {'.pdf'},
}

def validate_file_type(value):
    """Dateityp mit Magic-Bytes validieren."""
    kind = filetype.guess(value.read(2048))
    value.seek(0)

    if kind is None or kind.mime not in ALLOWED_MIMES:
        raise ValidationError('Nicht unterstützter Dateityp.')

    ext = os.path.splitext(value.name)[1].lower()
    if ext not in MIME_TO_EXTENSIONS.get(kind.mime, set()):
        raise ValidationError('Dateierweiterung stimmt nicht mit Dateiinhalt überein.')

Sicherer Dateispeicher

# settings.py
MEDIA_ROOT = '/var/www/media/'
MEDIA_URL = '/media/'

# In der Produktion eine separate Domain für Medien verwenden
MEDIA_DOMAIN = 'https://media.example.com'

# Benutzer-Uploads nicht direkt ausliefern
# whitenoise oder ein CDN für statische Dateien verwenden
# Einen separaten Server oder S3 für Mediendateien verwenden

API-Sicherheit

Ratenbegrenzung

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': [
        'rest_framework.throttling.AnonRateThrottle',
        'rest_framework.throttling.UserRateThrottle'
    ],
    'DEFAULT_THROTTLE_RATES': {
        'anon': '100/day',
        'user': '1000/day',
        'upload': '10/hour',
    }
}

# Benutzerdefinierte Drosselung
from rest_framework.throttling import UserRateThrottle

class BurstRateThrottle(UserRateThrottle):
    scope = 'burst'
    rate = '60/min'

class SustainedRateThrottle(UserRateThrottle):
    scope = 'sustained'
    rate = '1000/day'

Authentifizierung für APIs

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
}

# views.py
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated

@api_view(['GET', 'POST'])
@permission_classes([IsAuthenticated])
def secure_api(request):
    """Nur für authentifizierte Benutzer zugänglicher API-Endpunkt."""
    pass

Sichere Bereitstellung

Produktions-Checkliste

  • DEBUG = False setzen
  • Sicheren SECRET_KEY über Umgebungsvariablen verwenden
  • HTTPS mit einem gültigen SSL/TLS-Zertifikat aktivieren
  • ALLOWED_HOSTS korrekt konfigurieren
  • Datenbank mit sicheren Verbindungen und starken Passwörtern schützen
  • Sicherheitsheader implementieren (HSTS, CSP, etc.)
  • Regelmäßige Sicherheitsupdates mit pip audit oder ähnlichen Tools durchführen
  • Django-Sicherheits-Bulletins unter https://www.djangoproject.com/weblog/ verfolgen

Umgebungsvariablen

# .env-Datei (Niemals in die Versionskontrolle einchecken!)
DJANGO_SECRET_KEY=your-secret-key-here
DATABASE_URL=postgres://user:password@localhost:5432/dbname
ALLOWED_HOSTS=example.com,www.example.com

Zusätzliche Tools und Bibliotheken

  • django-axes: Brute-Force-Angriffe auf den Login überwachen und blockieren
  • django-allauth: Sichere Social-Auth-Integration
  • django-csp: Content Security Policy-Header verwalten
  • django-cors-headers: CORS-Header für APIs verwalten
  • django-ratelimit: Ratenbegrenzung auf View-Ebene
  • python-magic oder filetype: Dateitypvalidierung
  • bandit: Sicherheitslücken-Scanner für Python-Code
  • safety oder pip-audit: Abhängigkeiten auf bekannte Schwachstellen überprüfen

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

Verwandte Skills