How to Protect Sensitive Data in Django

How to Protect Sensitive Data in Django

The Internet is full of data, which is used for legal and illegal purposes. As a developer, we need to keep our system protect and secure. Securing applications will help our system to be protected from misuse. Security should be priority one once deploying an internet application on the web. The Django framework will a tremendous job providing reliable and secure Apis. However, none of that matters if we tend to don’t use them properly.

Our sensitive mostly kept in settings.py file. We can protect that data using Python Decouple Library. It is the library for separating parameters from the source code. We will create a file (Eg: .env or .ini) and keep some parameters in it, like database URL, password, secret key, debug status, email host, allowed hosts.

Why should we create .env or .ini file and keep parameters in it?

Let’s understand it by example. Suppose you have created a project and commit to GitHub which is public. Our Django Setting contains some parameters which are sensitive like secret_key, password. These parameters can be used by attackers for misuse. To avoid such situations we should not commit and keep it locally by ignoring in .gitignore file.

Install Python Decouple Library

pip install python-decouple 

Or download it from PyPI.

How to Use Python Decouple Library

Let’s consider settings.py file. for using the library.

import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SECRET_KEY = '6hv(7)$yiu&fzo#qb&*s-=$u14p5emb+ycamu7l@i1c!^hos!'
ALLOWED_HOSTS = ['localhost', '.herokuapp.com'] 
DEBUG = True
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'MY_DJANGO', # example - blog_data
        'USER': 'My_Django',
        'PASSWORD': '256hv(7)$y',
        'HOST': '127.0.0.1',
        'PORT': '80',
    }
}  

Create a .env or .ini file in your project root folder. See the Documentation.

Let’s say we want the secret key, database password, debug, etc to be hidden. So in yours.env file add a similar text like bellow and change accordingly to your application.

SECRET_KEY= 6hv(7)$yiu&fzo#qb&*s-=$u14p5emb+ycamu7l@i1c!^hos! 
DEBUG=True
DB_NAME= MY_DJANGO 
DB_USER=My_Django 
DB_PASSWORD=256hv(7)$y 
DB_HOST=127.0.0.1

If you are using Git, update your .gitignore file by adding the .env file, so you don’t commit any sensitive data to your remote repository.

Now in your settings.py, import the library

from decouple import config 

Retrieve the settings parameters from .env file-

import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SECRET_KEY = config('SECRET_KEY') 
DEBUG = config('DEBUG', cast=bool) 
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': config('DB_NAME'), 
        'USER': config('DB_USER'),
        'PASSWORD': config('DB_PASSWORD'),
        'HOST': config('DB_HOST'),
        'PORT': '80',
    }
}  

Casting Data

Let’s take an example, DEBUG expects Boolean value and EMAIL_PORT need integer. So we need to cast in the same data structure like below –

DEBUG = config('DEBUG', cast=bool)
EMAIL_PORT = config('EMAIL_PORT', cast=int)

You can also put ALLOWED_HOSTS like this

ALLOWED_HOSTS=.localhost, .herokuapp.com 

For accessing ALLOWED_HOSTS you can use a helper function CSV like this –

from decouple import config, Csv 

ALLOWED_HOSTS = config('ALLOWED_HOSTS', cast=Csv()) 

Default values

You can add an extra argument to the config function, to define a default value, in case there is an undefined value in the .env file.

DEBUG = config('DEBUG', default=True, cast=bool)

Meaning you won’t need to define the DEBUG parameter in the .env file in the development environment for example.

Share