0
0
DjangoHow-ToBeginner · 4 min read

How to Set Security Headers in Django for Safer Web Apps

In Django, you set security headers by adding middleware or configuring settings like SECURE_BROWSER_XSS_FILTER and SECURE_CONTENT_TYPE_NOSNIFF. You can also add custom headers using middleware to enhance protection against attacks such as XSS and clickjacking.
📐

Syntax

Django provides built-in settings and middleware to set common security headers. You can enable them in your settings.py file or create custom middleware to add headers manually.

Key settings include:

  • SECURE_BROWSER_XSS_FILTER = True - Enables the XSS filter in browsers.
  • SECURE_CONTENT_TYPE_NOSNIFF = True - Prevents MIME type sniffing.
  • X_FRAME_OPTIONS = 'DENY' - Prevents clickjacking by disallowing framing.

For custom headers, middleware must implement a __call__ or process_response method to add headers to the response.

python
class SecurityHeadersMiddleware:
    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'
        return response
💻

Example

This example shows how to enable Django's built-in security settings and add a custom middleware to set extra headers.

python
# settings.py

SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
X_FRAME_OPTIONS = 'DENY'

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.middleware.common.CommonMiddleware',
    'myapp.middleware.SecurityHeadersMiddleware',  # Custom middleware
    # other middleware...
]

# myapp/middleware.py

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

    def __call__(self, request):
        response = self.get_response(request)
        response['Referrer-Policy'] = 'no-referrer'
        response['Permissions-Policy'] = 'geolocation=()'
        return response
Output
When running the Django app, HTTP responses will include headers: X-Content-Type-Options: nosniff X-Frame-Options: DENY X-XSS-Protection: 1; mode=block Referrer-Policy: no-referrer Permissions-Policy: geolocation=()
⚠️

Common Pitfalls

  • Forgetting to add your custom middleware to the MIDDLEWARE list in settings.py.
  • Setting conflicting headers manually and via Django settings can cause unexpected behavior.
  • Not using SecurityMiddleware which handles some headers automatically.
  • Relying only on headers without HTTPS; headers like Strict-Transport-Security require HTTPS to be effective.
python
## Wrong: Missing middleware registration
# myapp/middleware.py
class SecurityHeadersMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    def __call__(self, request):
        response = self.get_response(request)
        response['X-Frame-Options'] = 'DENY'
        return response

# settings.py
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    # 'myapp.middleware.SecurityHeadersMiddleware' is missing here
]

## Right: Add middleware to settings
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'myapp.middleware.SecurityHeadersMiddleware',
]
📊

Quick Reference

Setting / HeaderPurposeExample Value
SECURE_BROWSER_XSS_FILTEREnable browser XSS filterTrue
SECURE_CONTENT_TYPE_NOSNIFFPrevent MIME sniffingTrue
X_FRAME_OPTIONSPrevent clickjacking'DENY' or 'SAMEORIGIN'
Strict-Transport-SecurityForce HTTPS (set via middleware)'max-age=31536000; includeSubDomains'
Referrer-PolicyControl referrer info sent'no-referrer'
Permissions-PolicyControl browser features'geolocation=()'

Key Takeaways

Use Django's built-in security settings like SECURE_BROWSER_XSS_FILTER and X_FRAME_OPTIONS to set common headers easily.
Add custom security headers by creating middleware that modifies the response headers.
Always register your custom middleware in the MIDDLEWARE list in settings.py.
Combine security headers with HTTPS for full protection, especially for headers like Strict-Transport-Security.
Test your headers using browser DevTools or online tools to ensure they are correctly applied.