Skip to main content

Django Security Settings

Introduction

Security is a critical aspect of web development. Django, as a mature web framework, comes with several built-in security features that can be configured through its settings module. Properly configuring these security settings helps protect your application against common threats like cross-site scripting (XSS), cross-site request forgery (CSRF), clickjacking, and other vulnerabilities.

In this tutorial, we'll explore Django's key security settings, understand their purpose, and learn how to configure them correctly for your projects.

Django's Security Philosophy

Django follows the principle of "secure by default." Many security features are enabled automatically when you create a new project. However, understanding these settings allows you to:

  1. Customize them based on your specific needs
  2. Add additional layers of security
  3. Make informed decisions when deploying to production

Core Django Security Settings

Let's explore the most important security settings in Django:

SECRET_KEY

The SECRET_KEY setting is one of the most crucial security settings in Django. It's used for:

  • Cryptographic signing
  • CSRF protection
  • Session security
python
# settings.py

# Never use this in production - this is just an example
SECRET_KEY = 'django-insecure-x#j*w!b=wmf4=hr4n$qu$1_76k)qzxr4fx+9c5==a_5m^5ovhi'

Best Practices:

  1. Keep your secret key... well, secret!
  2. Use environment variables in production:
python
# settings.py
import os
from django.core.management.utils import get_random_secret_key

# Load from environment variable or generate a new one
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', get_random_secret_key())
  1. Never commit your actual secret key to version control.

DEBUG Mode

The DEBUG setting controls Django's debug mode. In development, it provides helpful error pages, but in production, it can expose sensitive information:

python
# settings.py

# Development setting
DEBUG = True # Shows detailed error pages

# Production setting
DEBUG = False # Shows generic error pages

Best Practice: Always set DEBUG = False in production and configure it through environment variables:

python
# settings.py
import os

# Read from environment variable, default to False for safety
DEBUG = os.environ.get('DJANGO_DEBUG', '').lower() == 'true'

ALLOWED_HOSTS

When DEBUG = False, Django requires you to specify which hosts are allowed to serve your application:

python
# settings.py

# In development
ALLOWED_HOSTS = ['localhost', '127.0.0.1']

# In production
ALLOWED_HOSTS = ['www.yoursite.com', 'yoursite.com']

Security Implication: This prevents HTTP Host header attacks by validating the Host header in each request against this list.

CSRF Protection

Cross-Site Request Forgery (CSRF) protection is enabled by default in Django through middleware:

python
# settings.py

MIDDLEWARE = [
# ...
'django.middleware.csrf.CsrfViewMiddleware',
# ...
]

To use CSRF protection in your templates, include the CSRF token in your forms:

html
<form method="post">
{% csrf_token %}
<!-- form fields here -->
<button type="submit">Submit</button>
</form>

For AJAX requests, you need to include the CSRF token in your headers:

javascript
// JavaScript example
const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;

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

SECURE_SSL_REDIRECT

This setting forces all non-HTTPS requests to be redirected to HTTPS:

python
# settings.py

# In production
SECURE_SSL_REDIRECT = True

# In development
SECURE_SSL_REDIRECT = False

Best Practice: Enable this in production to enforce HTTPS.

Session Security Settings

Django provides several settings to secure your user sessions:

python
# settings.py

# Store session data in cookies (not in database)
SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"

# Prevent JavaScript from accessing session cookie
SESSION_COOKIE_HTTPONLY = True

# Send cookies only via HTTPS
SESSION_COOKIE_SECURE = True

# Session expiry (in seconds)
SESSION_COOKIE_AGE = 1209600 # 2 weeks

HTTP Strict Transport Security (HSTS)

HSTS tells browsers to only access your site using HTTPS:

python
# settings.py

# Enable HSTS
SECURE_HSTS_SECONDS = 31536000 # 1 year
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True

Note: Only enable HSTS when you're certain your site is properly configured for HTTPS, as it can make your site inaccessible if HTTPS is misconfigured.

Content Security Policy

Django doesn't have built-in CSP settings, but you can implement it using the django-csp package:

bash
pip install django-csp

Then add it to your settings:

python
# settings.py

MIDDLEWARE = [
# ...
'csp.middleware.CSPMiddleware',
# ...
]

# Example CSP settings
CSP_DEFAULT_SRC = ("'self'",)
CSP_STYLE_SRC = ("'self'", "'unsafe-inline'", "fonts.googleapis.com")
CSP_SCRIPT_SRC = ("'self'",)
CSP_FONT_SRC = ("'self'", "fonts.gstatic.com")
CSP_IMG_SRC = ("'self'", "data:")

Practical Example: Security Settings for a Production Django Application

Let's see how we can combine these settings in a production environment:

python
# production_settings.py

import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

# Security settings
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')
DEBUG = False
ALLOWED_HOSTS = [os.environ.get('DJANGO_ALLOWED_HOST')]

# HTTPS settings
SECURE_SSL_REDIRECT = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

# Session settings
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_HTTPONLY = True

# HSTS settings
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True

# Content security policy
MIDDLEWARE = [
# ... other middleware
'csp.middleware.CSPMiddleware',
]

CSP_DEFAULT_SRC = ("'self'",)
CSP_STYLE_SRC = ("'self'", "fonts.googleapis.com")
CSP_FONT_SRC = ("'self'", "fonts.gstatic.com")

Testing Your Security Settings

Django provides a convenient way to check if your security settings are properly configured:

bash
python manage.py check --deploy

This command will analyze your settings and provide recommendations for improving security.

Security Settings for Development vs. Production

It's a good practice to have separate settings for development and production environments:

python
# settings.py

# Base settings here...

if os.environ.get('DJANGO_ENV') == 'production':
from .production_settings import *
else:
from .development_settings import *

In your development_settings.py:

python
# development_settings.py

DEBUG = True
SECRET_KEY = 'dev-secret-key-for-local-use-only'
ALLOWED_HOSTS = ['localhost', '127.0.0.1']

# Disable production-only security features
SECURE_SSL_REDIRECT = False
SESSION_COOKIE_SECURE = False
CSRF_COOKIE_SECURE = False
SECURE_HSTS_SECONDS = 0

Summary

In this tutorial, we've covered Django's essential security settings:

  1. SECRET_KEY: Keep it secret and use environment variables
  2. DEBUG: Turn it off in production
  3. ALLOWED_HOSTS: Restrict which hosts can serve your application
  4. CSRF Protection: Enabled by default through middleware
  5. HTTPS Settings: Force HTTPS with settings like SECURE_SSL_REDIRECT
  6. Session Security: Configure cookies for enhanced security
  7. HSTS: Tell browsers to only use HTTPS
  8. Content Security Policy: Add an extra layer of protection against XSS attacks

Properly configuring these settings will significantly improve your Django application's security posture.

Additional Resources

Exercises

  1. Run the python manage.py check --deploy command on your current Django project and address at least three security issues it identifies.
  2. Create a strategy for storing your Django secret key as an environment variable in your development and production environments.
  3. Implement a Content Security Policy for your Django application using the django-csp package.
  4. Set up separate development and production settings files for one of your Django projects.

By implementing these security settings and following best practices, you'll build Django applications that are more resistant to common web security threats.



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)