Django storage based on Nginx secure links module
Project description
Django Nginx Secure Links
This module is a Django extension for using ngx_http_secure_link_module. It provides private urls with expiration lifetime by implementing described logic of ngx_http_secure_link_module. The major advantage of the extension is that Django delegates file serving on Nginx layer and does only pre-signed urls generation.
Requirements
Django Nginx Secure Links requires Django 3.2 or later.
Installation
Installing from PyPI is as easy as doing:
pip install django-nginx-secure-links
If you want to install it from source, grab the git repository from GitHub and run setup.py:
git clone git://github.com/lighTechLLC/django-nginx-secure-links.git
cd django-nginx-secure-links
python setup.py install
Nginx module set up
Option 1
Install using apt (Ubuntu example):
sudo apt install nginx-extras
Option 2
Build from sources:
./configure .... --with-http_secure_link_module
Quick example
Django settings set up settings.py:
INSTALLED_APPS = (
...
'nginx_secure_links',
...
)
MEDIA_ROOT = '/var/www/media/'
MEDIA_URL = '/media/'
SECURE_LINK_SECRET_KEY = 'KfM6aA6M7H'
Django < 4.2
DEFAULT_FILE_STORAGE = 'nginx_secure_links.storages.FileStorage'
Django >= 4.2
STORAGES = {
"default": {
"BACKEND": "nginx_secure_links.storages.FileStorage",
},
"staticfiles": {
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
},
}
Create a private file inside your settings.MEDIA_ROOT:
echo "I'm private text file" > /var/www/media/sample.txt
Let’s start runserver and access the file outside of Django file storage. It works and the file is available. There is no access denied, because of runserver mode:
curl http://127.0.0.1:8000/media/sample.txt
Set up Nginx virtual host file site.conf:
server 127.0.0.1;
listen 80;
...
location /media/ {
secure_link $arg_token,$arg_expires;
secure_link_md5 "$secure_link_expires$uri KfM6aA6M7H";
if ($secure_link = "") {
return 403;
}
if ($secure_link = "0") {
return 410;
}
alias /var/www/media/;
}
...
Let’s access the file through Nginx host/port.
curl http://127.0.0.1/media/sample.txt
Because of Nginx secure link module protection, the file won’t be served without ?token=...&expires=... parameters. Only django users will be able to access files which urls generated by django storage.
Usage
models.py
class Report(models.Model):
pdf_file = models.FileField(upload_to='reports')
views.py
def report_details(request, report_id)
instance = Report.objects.get(id=report_id)
return JsonResponse({'url': instance.pdf_file.url})
json response
{
"url": "/media/reports/29974.pdf?expires=1599214310&token=ErLcMm96-4h2qsuj2Avo-w"
}
That’s it, all uploaded media files through Django will be pre-signed. If you work locally and do not want to install Nginx, let’s skip it for local development- django will generate pre-signed urls, but all files will be available because of runserver command serves files and does not provide 3rd-party nginx-secure-link module functionality.
Settings
SECURE_LINK_SECRET_KEY
Your specific secret string which Nginx is going to use in secure_link_md5 directive.
SECURE_LINK_TOKEN_FIELD (optional, default: token)
Your custom name of the hash GET-parameter (?token=xyz)
SECURE_LINK_EXPIRES_FIELD (optional, default: expires)
Your custom name of expiration timestamp GET-parameter (?expires=1599215210)
SECURE_LINK_EXPIRATION_SECONDS (optional, default: 86400- 1 day)
Your custom value of expiration seconds. Any pre-signed link will be expired after SECURE_LINK_EXPIRATION_SECONDS.
SECURE_LINK_PRIVATE_PREFIXES (optional, default: [])
List of private paths without MEDIA_URL prefix. Just leave it empty for making all media urls private. Example:
MEDIA_URL = '/media/'
SECURE_LINK_PRIVATE_PREFIXES = [
'documents/',
'reports/',
]
In such case all /media/documents/ and /media/reports/ urls will be private and pre-signed by using token and expiration time. If any of existing prefixes on the project are not listed in SECURE_LINK_PRIVATE_PREFIXES, so the url will be public.
SECURE_LINK_PUBLIC_PREFIXES (optional, default: [])
List of private paths without MEDIA_URL prefix. Example:
MEDIA_URL = '/media/'
SECURE_LINK_PUBLIC_PREFIXES = [
'avatars/',
'shared/',
]
In such case only /media/avatars/ and /media/shared/ urls will be public and generated without pre-signed urls. All other urls, will be private and pre-signed by using token and expiration time.
Important If you want to keep all media files privately, SECURE_LINK_PRIVATE_PREFIXES and SECURE_LINK_PUBLIC_PREFIXES should be [].
Custom storage for non-media files
Example 1: We are going to use our own server directory and url prefix instead of settings.MEDIA_ROOT / settings.MEDIA_URL. The example is going to use all default settings.SECURE_LINK_*
from nginx_secure_links.storages import FileStorage
storage = FileStorage(location='/var/www/personal_data/', base_url='/personal/')
storage.url('profile.pdf')
storage.url('profile.pdf', lifetime=60)
storage.url('profile.pdf', lifetime=0)
Example 2: We are going to use custom storage with all overridden settings.
from nginx_secure_links.storages import FileStorage
storage = FileStorage(
location='/var/www/personal_data/',
base_url='/personal/'
nginx_secret_key='91rdywY7d4494X',
expires_field_name='expires_timestamp',
token_field_name='hash',
private_prefixes=[],
public_prefixes=[],
expires_seconds=60 * 60, # 60min
) # all private
storage.url('profile.pdf') # /personal/profile.pdf?hash=mlkiuhbhu83d&expires_timestamp=2147483647
Using It
Generate pre-signed url by passing public url:
python manage.py secure_links_gen_signed /media/reports/sample.pdf
Generates a sample of Nginx location basing on the settings:
python manage.py secure_links_nginx_location
Found a Bug?
Issues are tracked via GitHub issues at the project issue page.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file django_nginx_secure_links-0.0.9.tar.gz
.
File metadata
- Download URL: django_nginx_secure_links-0.0.9.tar.gz
- Upload date:
- Size: 9.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.3
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 399f0c29fca175a9a4f99405838473317c3c29dfa2de5c26ac1ac5dcc586cfac |
|
MD5 | bcdbbc730572ea9650991ba3b59b6b78 |
|
BLAKE2b-256 | 62b57029a0cd1f3e0ba83eecfb86882679d26daf5a77456f59076b4aaa6d578b |
File details
Details for the file django_nginx_secure_links-0.0.9-py3-none-any.whl
.
File metadata
- Download URL: django_nginx_secure_links-0.0.9-py3-none-any.whl
- Upload date:
- Size: 10.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.3
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5854bdc53f9cddcd82b5c8092e1111fb1eb2048e77e40535ed685dab40bb5e40 |
|
MD5 | eec7e84bdd31e8a974d5a199d7ba78be |
|
BLAKE2b-256 | 1c44f07d464441fa6834b6c8fd2fda828854115004cc38178e0c91069a6b5bfe |