3👍
AFAIK, This is the purpose of CSRF, to avoid posting data from unknown strange sources. You need csrf token to post this which django generates dynamically.
0👍
Upgrading Django might fix the missing Referer error.
As of Django 4.0 (release notes), the backend will first check the Origin
header before falling back to the Referer
header (source):
CsrfViewMiddleware
verifies the Origin header, if provided by the browser, against the current host and theCSRF_TRUSTED_ORIGINS
setting. This provides protection against cross-subdomain attacks.- In addition, for HTTPS requests, if the
Origin
header isn’t provided,CsrfViewMiddleware
performs strict referer checking. This means that even if a subdomain can set or modify cookies on your domain, it can’t force a user to post to your application since that request won’t come from your own exact domain.
- [Django]-Alternative for Aldryn-forms (Django-CMS)
- [Django]-Django: BooleanField return 'on' instead of true?
- [Django]-MongoDB storage along with MySQL XPath features
- [Django]-Django does not find Pillow though installed
- [Django]-Alternatives to the default django template system
0👍
It’s possible you have a reverse proxy running, for example an nginx proxy_pass
to 127.0.0.1:8000
?
In this case, Django expects the Cross-Site Forgery Protection tokens to match hostname 127.0.0.1
, but they will be coming from a normal domain (for example example.com
).
Expected Source | Actual Source |
---|---|
http://127.0.0.1 | https://example.com |
HTTP reverse proxy (example.com:80
-> localhost:3000
) is a common way to use nginx with NodeJS applications, but it doesn’t work well with Django
Client-Facing URL | Server Proxy URL |
---|---|
https://example.com | http://127.0.0.1:3000 |
It is better to run Django through a Unix socket rather than a port (example.com:80
-> <socket>
). You can do this with Gunicorn:
Client-Facing URL | Server Proxy URL |
---|---|
https://example.com | unix:/run/example.com.sock |
Here’s how to do this with Django, Gunicorn, and nginx:
Let’s say you’ve got a Django project root, which contains a system folder (the one where settings.py
and wsgi.py
are):
export DJANGO_PROJECT_PATH=/path/to/django/root
export DJANGO_SETTING_FOLDER=system
First, make sure you have Gunicorn installed and that you are using a virtual environment:
cd $DJANGO_PROJECT_PATH
source .venv/bin/activate # <- Use a virtual environment
pip3 install gunicorn # <- install Gunicorn in the venv
Run Gunicorn. This will start the Django project similar to running python3 manage.py runserver
, except that you can listen for requests on a Unix socket:
$DJANGO_PROJECT_PATH/.venv/bin/gunicorn \
--workers=3 \
--access-logfile - \
--bind unix:/run/example.com.sock \ # <- Socket
--chdir=$DJANGO_PROJECT_PATH/ \
$DJANGO_SETTING_FOLDER.wsgi:application
Then create an HTTP proxy using nginx that passes HTTP requests from clients through the gunicon-created socket:
/etc/nginx/sites-enabled/example.com
:
server {
listen 80;
listen [::]:80;
server_name example.com;
# serve static files directly through nginx
location /static/ {
autoindex off;
root /path/to/django/root;
}
# serve user-uploaded files directly through nginx
location /media/ {
autoindex off;
root /path/to/django/root;
}
# You can do fun stuff like aliasing files from other folders
location /robots.txt {
alias /path/to/django/root/static/robots.txt;
}
# here is the proxy magic
location / {
include proxy_params;
proxy_pass http://unix:/run/example.com.sock; # <- the socket!
}
}
Make sure to restart nginx:
sudo service restart nginx
After all this, your csrf tokens should match the domain name of your site and you’ll be able to log in and submit forms.
- [Django]-May not set both `read_only` and `write_only`
- [Django]-Django – how to restrict DeleteView to object owner
- [Django]-413 Request Entity Too Large – Regular Fix Not Working
- [Django]-Django absract vs non-abstract model inheritance