Pretty new to Django. Working through a second project following the Polls tutorial on Django website. Previous effort went well, albeit simple. This time around encountering problems accessing admin login.
I have created a superuser and using those credentials, when I try to login to http://127.0.0.1:8000/admin/login/?next=/admin/
I get the following error:
Forbidden (403)
CSRF verification failed. Request aborted.
Reason given for failure:
CSRF cookie not set.
Looking at this and this, most answers either detail clearing browser cookies (did that), include 'django.middleware.csrf.CsrfViewMiddleware'
in your middleware (which I do), or creating an exemption or workaround.
1) My question is why the admin portal does not seem to work now, but it did for my previous project and I am following the same steps?
2) Shouldn’t the properties for the admin panel be inherited through the project initiation?
3) How would I set the CSRF for admin when the documentation appears to state that the CSRF middleware is activated by default?
Thanks for any help.
settings.py
"""
Django settings for aptly project.
Generated by 'django-admin startproject' using Django 1.9.7.
For more information on this file, see
https://docs.djangoproject.com/en/1.9/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.9/ref/settings/
"""
import os
import dj_database_url
from .secret_settings import *
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
PROJECT_DIR = os.path.join(PROJECT_ROOT,'../search')
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'search',
]
MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'aptly.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'aptly.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.9/ref/settings/#databases
DATABASES = {
'default': {
"ENGINE": "django.db.backends.postgresql_psycopg2",
"NAME": "db_name",
"USER": "me",
"PASSWORD": "",
"HOST": "localhost",
"PORT": "",
}
}
# Password validation
# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/1.9/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static_root')
# Extra places for collectstatic to find static files.
STATICFILES_DIRS = (
os.path.join(PROJECT_DIR, 'static'),
)
# Simplified static file serving.
# https://warehouse.python.org/project/whitenoise/
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
#DATABASES['default'] = dj_database_url.config()
urls.py
from django.conf.urls import patterns, include, url
from django.contrib import admin
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^admin/', admin.site.urls),
]
Directory
project
-aptly
--settings.py
--urls.py
--wsgi.py
-search
--templates
---index.html
--models.py
--urls.py
--views.py
manage.py
How to use Django’s CSRF protection¶
To take advantage of CSRF protection in your views, follow these steps:
-
The CSRF middleware is activated by default in the
MIDDLEWARE
setting. If you override that setting, remember that
'django.middleware.csrf.CsrfViewMiddleware'
should come before any view
middleware that assume that CSRF attacks have been dealt with.If you disabled it, which is not recommended, you can use
csrf_protect()
on particular views
you want to protect (see below). -
In any template that uses a POST form, use the
csrf_token
tag inside
the<form>
element if the form is for an internal URL, e.g.:<form method="post">{% csrf_token %}
This should not be done for POST forms that target external URLs, since
that would cause the CSRF token to be leaked, leading to a vulnerability. -
In the corresponding view functions, ensure that
RequestContext
is used to render the response so
that{% csrf_token %}
will work properly. If you’re using the
render()
function, generic views, or contrib apps,
you are covered already since these all useRequestContext
.
Using CSRF protection with AJAX¶
While the above method can be used for AJAX POST requests, it has some
inconveniences: you have to remember to pass the CSRF token in as POST data with
every POST request. For this reason, there is an alternative method: on each
XMLHttpRequest, set a custom X-CSRFToken
header (as specified by the
CSRF_HEADER_NAME
setting) to the value of the CSRF token. This is
often easier because many JavaScript frameworks provide hooks that allow
headers to be set on every request.
First, you must get the CSRF token. How to do that depends on whether or not
the CSRF_USE_SESSIONS
and CSRF_COOKIE_HTTPONLY
settings
are enabled.
Acquiring the token if CSRF_USE_SESSIONS
and CSRF_COOKIE_HTTPONLY
are False
¶
The recommended source for the token is the csrftoken
cookie, which will be
set if you’ve enabled CSRF protection for your views as outlined above.
The CSRF token cookie is named csrftoken
by default, but you can control
the cookie name via the CSRF_COOKIE_NAME
setting.
You can acquire the token like this:
function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } const csrftoken = getCookie('csrftoken');
The above code could be simplified by using the JavaScript Cookie library to replace getCookie
:
const csrftoken = Cookies.get('csrftoken');
Note
The CSRF token is also present in the DOM in a masked form, but only if
explicitly included using csrf_token
in a template. The cookie
contains the canonical, unmasked token. The
CsrfViewMiddleware
will accept either.
However, in order to protect against BREACH attacks, it’s recommended to
use a masked token.
Warning
If your view is not rendering a template containing the csrf_token
template tag, Django might not set the CSRF token cookie. This is common in
cases where forms are dynamically added to the page. To address this case,
Django provides a view decorator which forces setting of the cookie:
ensure_csrf_cookie()
.
Setting the token on the AJAX request¶
Finally, you’ll need to set the header on your AJAX request. Using the
fetch() API:
const request = new Request( /* URL */, { method: 'POST', headers: {'X-CSRFToken': csrftoken}, mode: 'same-origin' // Do not send CSRF token to another domain. } ); fetch(request).then(function(response) { // ... });
Using CSRF protection in Jinja2 templates¶
Django’s Jinja2
template backend
adds {{ csrf_input }}
to the context of all templates which is equivalent
to {% csrf_token %}
in the Django template language. For example:
<form method="post">{{ csrf_input }}
Using the decorator method¶
Rather than adding CsrfViewMiddleware
as a blanket protection, you can use
the csrf_protect()
decorator, which has
exactly the same functionality, on particular views that need the protection.
It must be used both on views that insert the CSRF token in the output, and
on those that accept the POST form data. (These are often the same view
function, but not always).
Use of the decorator by itself is not recommended, since if you forget to
use it, you will have a security hole. The ‘belt and braces’ strategy of using
both is fine, and will incur minimal overhead.
Handling rejected requests¶
By default, a ‘403 Forbidden’ response is sent to the user if an incoming
request fails the checks performed by CsrfViewMiddleware
. This should
usually only be seen when there is a genuine Cross Site Request Forgery, or
when, due to a programming error, the CSRF token has not been included with a
POST form.
The error page, however, is not very friendly, so you may want to provide your
own view for handling this condition. To do this, set the
CSRF_FAILURE_VIEW
setting.
CSRF failures are logged as warnings to the django.security.csrf logger.
Using CSRF protection with caching¶
If the csrf_token
template tag is used by a template (or the
get_token
function is called some other way), CsrfViewMiddleware
will
add a cookie and a Vary: Cookie
header to the response. This means that the
middleware will play well with the cache middleware if it is used as instructed
(UpdateCacheMiddleware
goes before all other middleware).
However, if you use cache decorators on individual views, the CSRF middleware
will not yet have been able to set the Vary header or the CSRF cookie, and the
response will be cached without either one. In this case, on any views that
will require a CSRF token to be inserted you should use the
django.views.decorators.csrf.csrf_protect()
decorator first:
from django.views.decorators.cache import cache_page from django.views.decorators.csrf import csrf_protect @cache_page(60 * 15) @csrf_protect def my_view(request): ...
If you are using class-based views, you can refer to Decorating
class-based views.
Testing and CSRF protection¶
The CsrfViewMiddleware
will usually be a big hindrance to testing view
functions, due to the need for the CSRF token which must be sent with every POST
request. For this reason, Django’s HTTP client for tests has been modified to
set a flag on requests which relaxes the middleware and the csrf_protect
decorator so that they no longer rejects requests. In every other respect
(e.g. sending cookies etc.), they behave the same.
If, for some reason, you want the test client to perform CSRF
checks, you can create an instance of the test client that enforces
CSRF checks:
>>> from django.test import Client >>> csrf_client = Client(enforce_csrf_checks=True)
Edge cases¶
Certain views can have unusual requirements that mean they don’t fit the normal
pattern envisaged here. A number of utilities can be useful in these
situations. The scenarios they might be needed in are described in the following
section.
Disabling CSRF protection for just a few views¶
Most views requires CSRF protection, but a few do not.
Solution: rather than disabling the middleware and applying csrf_protect
to
all the views that need it, enable the middleware and use
csrf_exempt()
.
Setting the token when CsrfViewMiddleware.process_view()
is not used¶
There are cases when CsrfViewMiddleware.process_view
may not have run
before your view is run — 404 and 500 handlers, for example — but you still
need the CSRF token in a form.
Solution: use requires_csrf_token()
Including the CSRF token in an unprotected view¶
There may be some views that are unprotected and have been exempted by
csrf_exempt
, but still need to include the CSRF token.
Solution: use csrf_exempt()
followed by
requires_csrf_token()
. (i.e. requires_csrf_token
should be the innermost decorator).
Protecting a view for only one path¶
A view needs CSRF protection under one set of conditions only, and mustn’t have
it for the rest of the time.
Solution: use csrf_exempt()
for the whole
view function, and csrf_protect()
for the
path within it that needs protection. Example:
from django.views.decorators.csrf import csrf_exempt, csrf_protect @csrf_exempt def my_view(request): @csrf_protect def protected_path(request): do_something() if some_condition(): return protected_path(request) else: do_something_else()
Protecting a page that uses AJAX without an HTML form¶
A page makes a POST request via AJAX, and the page does not have an HTML form
with a csrf_token
that would cause the required CSRF cookie to be sent.
Solution: use ensure_csrf_cookie()
on the
view that sends the page.
CSRF protection in reusable applications¶
Because it is possible for the developer to turn off the CsrfViewMiddleware
,
all relevant views in contrib apps use the csrf_protect
decorator to ensure
the security of these applications against CSRF. It is recommended that the
developers of other reusable apps that want the same guarantees also use the
csrf_protect
decorator on their views.
Содержание
- Unable to Login Django Admin after Update : Giving Error Forbidden (403) CSRF verification failed. Request aborted.
- Problem
- Details
- First Solution
- Second Solution
- Third Solution
- Conclusion
- Top comments (0)
- Update Your DEV Experience Level:
- How to resolve Forbidden(403) if Django CSRF mechanism has not been used in POST method
- Cross Site Request Forgery protection
- 1. FORM
- 2. IN AJAX
- Issues
- Context Navigation
- #28488 closed Bug (fixed)
- Django 1.11+ raises CSRF verification failed if settings.DEBUG is False and an intermediate 404 page is requested
- Description (last modified by Ruben Alves )
- Attachments (3)
- Change History (44)
- Changed 5 years ago by Ruben Alves
- comment:1 Changed 5 years ago by Ruben Alves
- comment:2 Changed 5 years ago by Tim Graham
- comment:3 Changed 5 years ago by Ruben Alves
- comment:4 Changed 5 years ago by Tim Graham
- comment:5 Changed 5 years ago by Ruben Alves
- comment:6 Changed 5 years ago by Tim Graham
- comment:7 Changed 5 years ago by Ruben Alves
- comment:8 Changed 5 years ago by Tim Graham
- comment:9 Changed 5 years ago by Ruben Alves
- comment:10 Changed 5 years ago by Ruben Alves
- comment:11 Changed 5 years ago by Ruben Alves
- comment:12 Changed 5 years ago by Ruben Alves
- CSRF error on all POST requests #1912
- Comments
- Expected behaviour
- Actual behaviour
- Server configuration
Unable to Login Django Admin after Update : Giving Error Forbidden (403) CSRF verification failed. Request aborted.
Problem
Unable to Login Django Admin after Update : Giving Error Forbidden (403) CSRF verification failed. Request aborted.
This Issue Can happened suddenly after updating to Newer Version Of Django which looks like below image.
Details
Django Project Foundation team made some changes in security requirements for all Django Version 4.0 and Above. In Which they made mandatory to create an list of urls getting any type of form upload or POST request in project settings named as CSRF_TRUSTED_ORIGINS.
They did not updated the details in latest tutorial documentation but they published the Changes Notes at https://docs.djangoproject.com/en/4.0/releases/4.0/#csrf-trusted-origins-changes-4-0.
First Solution
Goto settings.py of your django project and create a new list of urls at last like given below
Exit fullscreen mode
if Your running an project in localhost then you should open all urls here * symbol means all urls also there is http:// is mandatory.
Second Solution
This is Also for Localhost and for DEBUG=True .
Copy the list of ALLOWED_ORIGINS into CSRF_TRUSTED_ORIGINS like given below.
Exit fullscreen mode
Third Solution
When Deploying you have to add urls to allow form uploading ( making any POST request ).
I Know this maybe tricky and time consuming but it’s now mandatory.
Also this is Mandatory to Online IDEs also like Replit, Glitch and Many More.
Conclusion
If you found this useful then please share this and follow me! Also check out Buy Me A Coffee if you want to support me on a new level!
Give an reaction if any solutions helped you for algorithm boost to my content.
For further actions, you may consider blocking this person and/or reporting abuse
Update Your DEV Experience Level:
Go to your customization settings to nudge your home feed to show content more relevant to your developer experience level. 🛠
Источник
How to resolve Forbidden(403) if Django CSRF mechanism has not been used in POST method
Are you a newbie to Django like me. ?
if yes , you would have come across “Forbidden (403)” when you are using forms or when you have used ajax post method to your app view and have not used CSRF mechanism properly. Below are ways I have resolved the 403 issues. Even before we see how CSRF should be used, we will see what CSRF is actually for.
Cross Site Request Forgery protection
“ The CSRF middleware and template tag provides easy-to-use protection against Cross Site Request Forgeries. This type of attack occurs when a malicious website contains a link, a form button or some JavaScript that is intended to perform some action on your website, using the credentials of a logged-in user who visits the malicious site in their browser. A related type of attack, ‘login CSRF’, where an attacking site tricks a user’s browser into logging into a site with someone else’s credentials, is also covered.”
CSRF middleware is enabled by default in your project settings.py file like below
Alternatively, If this is not enabled or set, you can still use the protection by decorating your views with csrf_protect
Ok now we have csrf protection on our views. Let us see how we can use it.
Using the csrf middleware token. Csrf middle ware token looks something like this below
1. FORM
We have to use the csrf_token tag inside the element if the form .for internal url
2. IN AJAX
First, we need to get the crsf cookie and this depends on whether CSRF_USE_SESSIONS and CSRF_COOKIE_HTTPONLY.
i) If CSRF_USE_SESSIONS and CSRF_COOKIE_HTTPONLY are False. You can get the cookie by using below function as in django documentation
Now the cookie is stored in csrftoken variable which can be used later in your ajax post.
Alternatively, you can also use the CND javascript library
You can then use the library method Cookies.get() to get cookie.
ii) If CSRF_USE_SESSIONS and CSRF_COOKIE_HTTPONLY are True
You can simply use jquery to get the cookie value like below
Secondly that we have the csrftoken available, we can simply specify in our ajax post method. In my example, I have used the jquery post method.
Now when you post to server URL, Django will process the request and there should be no 403 error.
Источник
Issues
Context Navigation
#28488 closed Bug (fixed)
Django 1.11+ raises CSRF verification failed if settings.DEBUG is False and an intermediate 404 page is requested
Reported by: | Ruben Alves | Owned by: | nobody |
---|---|---|---|
Component: | CSRF | Version: | dev |
Severity: | Release blocker | Keywords: | csrf failed settings debug false production |
Cc: | rubenanapu@…, Nicola, Jay Cox, Florian Apolloner, Berker Peksag | Triage Stage: | Accepted |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by Ruben Alves )
I’m using Django1.11 (and made tests also with Django1.11.4) and having problems when submitting a form with POST method.
I’m calling the <% csrf_token %>inside of the form, so, this is not the problem.
The problem when submitting the form is:
Forbidden (403)
CSRF verification failed. Request aborted.
More information is available with DEBUG=True.
Then, in order to see «more information», I’ve enabled settings.DEBUG to True and submitted the form again. At this moment, the problem didn’t happens anymore.
So I’ve disabled settings.DEBUG , submitted again, and the problem was there. Enabled DEBUG=True again, problem has gone.
Initially I thought that could be some error in my code, but the same happens when I try to reset my password wit the django.contrib.auth.views.password_reset view.
In my settings.py , I have the following changes that were made recently:
SECURE_PROXY_SSL_HEADER = (‘HTTP_X_FORWARDED_PROTO’, ‘https’)
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
I use AWS (Amazon Web Service) Elastic Beanstalk with https enabled.
The worst part is that I’ve discovered this only on production because I make all tests in my local machine with DEBUG=True , and on production, we set DEBUG=False . Also, the error message should be shown only if DEBUG=True .
Attachments (3)
Download all attachments as: .zip
Change History (44)
Changed 5 years ago by Ruben Alves
Error message on production with settings.DEBUG=False
Did you experience a change in Django 1.11 compared to Django 1.10 or earlier? I think you’ll need to debug the problem further and let us know why Django is at fault.
Before Django 1.11, I was using Django 1.8 and everything was working perfectly.
In order to use Django 1.11, I did all the changes mentioned on https://docs.djangoproject.com/en/1.11/releases/1.11/
What I’ve done now was add settings.CSRF_FAILURE_VIEW = ‘courses.views.csrf_failure’ with DEBUG=False
I made my courses.views.csrf_failure raise an exception, so we could see the traceback.
The error message is:
The traceback is the following:
The traceback doesn’t give me any ideas about the cause. I think you’ll need to add further logging in django/middleware/csrf.py to find the root cause.
A large CSRF change between Django 1.8 and 1.11 is 5112e65ef2df1dbb95ff83026b6a962fb2688661. Perhaps you can test with Django 1.9 and 1.10 to help narrow the problem.
In the backwards-incompatible changes section of the 1.10 release notes, there’s a note, «CSRF token values are now required to be strings of 64 alphanumerics; values of 32 alphanumerics, as set by older versions of Django by default, are automatically replaced by strings of 64 characters. Other values are considered invalid. This should only affect developers or users who replace these tokens.» Maybe it’s relevant to you.
Ok, I’ve added some logs on django.middleware.csrf , and this is what I have:
Between lines 208 and 209 ( https://github.com/django/django/blob/stable/1.11.x/django/middleware/csrf.py#L208) I’ve added a log and the value of csrf_token is vcdodHkRb8jlxQP5fnTjuQp5i3PMWYYEBOYfpOFkCEjWWwHMpJ9uqaPGI6vGi6hS
The value of request_csrf_token on line 311 ( https://github.com/django/django/blob/stable/1.11.x/django/middleware/csrf.py#L311) before we call request_csrf_token = _sanitize_token(request_csrf_token) is tMgl4aTrdjOEShUax3Gz1CJLbvnhBWiEVzmzgTxSclDuP01lBfwoE2R6dDyljaCQ
After _sanitize_token be called, the value of request_csrf_token is the same, and the value of csrf_token is vcdodHkRb8jlxQP5fnTjuQp5i3PMWYYEBOYfpOFkCEjWWwHMpJ9uqaPGI6vGi6hS .
Maybe you can try to minimize the middleware, etc. in your project and see if something like that is causing the issue.
I’ve being testing to reload the page and see the Cookie named csrftoken .
On the system that runs with Django1.8 , every time I reload the page, the csrftoken Cookie has the same value.
On the system that runs with Django1.11 , every time I reload the page, the csrftoken Cookie has a different value.
Do you know if on Django1.11 is expected to have a different csrftoken Cookie every time I reload the page? If yes, why is expected to be different in Django1.11 and not in Django1.8 ?
But even if they are different, the function _unsalt_cipher_token ( https://github.com/django/django/blob/stable/1.11.x/django/middleware/csrf.py#L62) should return always the same value with the different values on the Cookie, right?
I’ve called the _unsalt_cipher_token function with the different values of the Cookie, and the returned values are ALWAYS different.
I’ve created a template tag named uncypher that calls _unsalt_cipher_token as you can see below:
Then, on a html template I’ve added
After set settings.DEBUG=True and reload the page 3 times, on the JavaScript Console was printed the same value lKnMEqisHw8mxMIXZgZTKt9cirypfv1f on the 3 times that I’ve reloaded the page.
Then I’ve set settings.DEBUG=False and reloaded the page 4 times again.
On the first time it printed the same value lKnMEqisHw8mxMIXZgZTKt9cirypfv1f . On the second YgnNvwBJJwAID17nl7FLhtA3rObtvGLX , third time printed hB1plGV688FpDPNu9waO1H959c04YLPM and fourth time printed C2sJ9e7coe74juO6HxAY4RIppBY4yi1Y .
Tested the system with Django1.10 and Django1.11 .
With Django1.10 everything works. With Django1.11 we have the error.
I finally solved my problem.
The problem is: If a user just get a 404 page, a new CSRF Token is generated, invalidating the CSRF Token that was originally loaded with <% csrf_token %>.
How I’ve discovered
On the WebSite that I work, we have a page with the URI /en/courses/ .
On that page, on the .html file we include a JavaScript:
The app.js was trying to load a file named assets/js/particles.json using the relative path, so the final URL of the static file was /en/courses/assets/js/particles.json . Load the particles.json is the only thing that app.js was doing. Nothing else.
That particles.json doesn’t exist on our system.
After successfully load /en/courses/ , the Django Server was receiving a request for /en/courses/assets/js/particles.json that raises a 404 error for the static file, but this error 404 is not even noticed by the users because this JS file was doing nothing.
After I remove this , everything worked fine.
Then with debugs on the django.middleware.csrf.CsrfViewMiddleware I could confirm that if I reload a page 1000 times, the CSRF Token returned by _unsalt_cipher_token ( https://github.com/django/django/blob/stable/1.11.x/django/middleware/csrf.py#L62) is always the same. But if I just try to access a page that doesn’t exist, then _unsalt_cipher_token returns a different value (a new token is generated).
Unbelievable that a single javascript that doesn’t even exist has broken my system and took me 3 days to find out.
Источник
CSRF error on all POST requests #1912
I have set up weblate using the documentation without docker. It is running from a virtualenv, served by gunicorn with an nginx in front of it. HTTPS is set up in front (I am using correct.example.com here for the correct HTTPS hostname), the following settings are changed from the default settings:
Expected behaviour
Actual behaviour
When I attempt a login: «CSRF verification failed. Request aborted.»
I have observed the following:
- Every time I reload, the CSRF token in the HTML changes even when I have CSRF_USE_SESSIONS = True . The session cookie stays identical.
- On a single response, the «Set-cookie: csrftoken» header and the CSRF token in the HTML is different when I have CSRF_USE_SESSIONS = False
- ENABLE_HTTPS = False or CSRF_COOKIE_SECURE = False do not help
- With debugging enabled, I can see the following log messages:
lib/python2.7/site-packages/django/template/defaulttags.py:66: UserWarning: A <% csrf_token %>was used in a template, but the context did not provide the value. This is usually caused by not using RequestContext. as well as Forbidden (Referer checking failed — https://correct.example.com/ does not match any trusted origins.): /accounts/register/
Server configuration
Please paste the output of command ./manage.py list_versions over here
- Weblate 2.19.1
- Python 2.7.5
- Django 1.11.11
- six 1.11.0
- social-auth-core 1.7.0
- social-auth-app-django 2.1.0
- django-appconf 1.0.2
- Translate Toolkit 2.3.0
- Whoosh 2.7.4
- defusedxml 0.5.0
- Git 1.8.3.1
- Pillow (PIL) 1.1.7
- dateutil 2.7.0
- lxml 4.2.0
- django-crispy-forms 1.7.2
- compressor 2.2
- djangorestframework 3.7.7
- user-agents 1.1.0
- pytz 2018.3
- pyuca N/A
- python-bidi 0.4.0
- pyLibravatar N/A
- PyYAML 3.12
- Database backends: django.db.backends.mysql
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.
The text was updated successfully, but these errors were encountered:
Источник
При попытке входа в админку Django 4.* возникает 403-я ошибка CSRF Protection.
Согласно списку изменений CSRF_TRUSTED_ORIGINS changes в Django 4.*, вы должны добавить настройку CSRF_TRUSTED_ORIGINS в settings.py с явным указанием http протокола (‘http://’ иили ‘https://’)
Мои настройки выглядят следующим образом:
if DEBUG: CSRF_TRUSTED_ORIGINS = ['http://*', 'https://*'] if not DEBUG: CSRF_TRUSTED_ORIGINS = ['http://*.your-domain.ru', 'https://*.your-domain.ru'] # FIX admin CSRF token issue
Другие публикации из блога
Применяем разные сериализаторы для разных действий в Django Rest Framework GenericViewSet
Фактически нам нужно переопределить метод get_serializer_class() и с помощью условий добавить разные сериализаторы для …
Подробнее
Как запустить, перезапустить, остановить, узнать статус Nginx в Ubuntu?
Systemctl: startrestartstopstatus
sudo systemctl restart nginx
sudo systemctl start nginx
sudo systemctl sto…
Подробнее
JavaScript fetch с простой HTTP аутентификацией
Самый простой способ протестировать ваш API с базовой аутентификацией (логин, пароль).
Аналогичным образом работ…
Подробнее
Как создать virtualenv с разными версиями Python в Windows
Прежде всего у вас должны быть установлены разные версии Python в системе + virtualenv.
Ниже пример создания виртуал…
Подробнее
Разница между операторами «is» и «==» в Python
Оба оператора is и == предназначены для сравнения объектов в Python.
Оператор == сравнивает два значения.
Операто…
Подробнее
Как сгенерировать SECRET_KEY в Django?
Заходим в терминал:
python manage.py shell
Импортируем utils:
from django.core.management import utils
Гене…
Подробнее
Problem
Unable to Login Django Admin after Update : Giving Error Forbidden (403) CSRF verification failed. Request aborted.
This Issue Can happened suddenly after updating to Newer Version Of Django which looks like below image.
Details
Django Project Foundation team made some changes in security requirements for all Django Version 4.0 and Above. In Which they made mandatory to create an list of urls getting any type of form upload or POST request in project settings named as CSRF_TRUSTED_ORIGINS.
They did not updated the details in latest tutorial documentation but they published the Changes Notes at https://docs.djangoproject.com/en/4.0/releases/4.0/#csrf-trusted-origins-changes-4-0.
First Solution
For
localhost
or127.0.0.1
.Goto
settings.py
of your django project and create a new list of urls at last like given below
CSRF_TRUSTED_ORIGINS = ['http://*', 'https://*']
Enter fullscreen mode
Exit fullscreen mode
if Your running an project in localhost then you should open all urls here
*
symbol means all urls also there ishttp://
is mandatory.
Second Solution
This is Also for Localhost and for
DEBUG=True
.Copy the list of ALLOWED_ORIGINS into CSRF_TRUSTED_ORIGINS like given below.
ALLOWED_ORIGINS = ['http://*', 'https://*']
CSRF_TRUSTED_ORIGINS = ALLOWED_ORIGINS.copy()
Enter fullscreen mode
Exit fullscreen mode
Third Solution
When Deploying you have to add urls to allow form uploading ( making any POST request ).
I Know this maybe tricky and time consuming but it’s now mandatory.
Also this is Mandatory to Online IDEs also like Replit, Glitch and Many More.
Conclusion
If you found this useful then please share this and follow me! Also check out Buy Me A Coffee if you want to support me on a new level!
Give an reaction if any solutions helped you for algorithm boost to my content.
bye 👋.
Чтобы воспользоваться преимуществами защиты от CSRF в ваших представлениях, выполните следующие шаги:
-
По умолчанию промежуточное ПО CSRF активировано в настройках
MIDDLEWARE
. Если вы переопределите эту настройку, помните, что'django.middleware.csrf.CsrfViewMiddleware'
должно стоять перед любым промежуточным ПО представления, которое предполагает, что CSRF-атаки были обработаны.Если вы отключили его, что не рекомендуется, вы можете использовать
csrf_protect()
на определенных представлениях, которые вы хотите защитить (см. ниже). -
В любом шаблоне, использующем форму POST, используйте тег
csrf_token
внутри элемента<form>
, если форма предназначена для внутреннего URL, например:<form method="post">{% csrf_token %}
Этого не следует делать для POST-форм, нацеленных на внешние URL, поскольку в этом случае произойдет утечка CSRF-токена, что приведет к уязвимости.
-
В соответствующих функциях представления убедитесь, что
RequestContext
используется для рендеринга ответа, чтобы{% csrf_token %}
работал правильно. Если вы используете функциюrender()
, общие представления или приложения contrib, вы уже защищены, поскольку все они используютRequestContext
.
Использование защиты CSRF в AJAX¶
Хотя описанный выше метод можно использовать для AJAX POST-запросов, он имеет некоторые неудобства: вы должны помнить о необходимости передавать CSRF-токен в качестве POST-данных при каждом POST-запросе. По этой причине существует альтернативный метод: при каждом XMLHttpRequest устанавливайте в пользовательский заголовок X-CSRFToken
(как указано в настройке CSRF_HEADER_NAME
) значение маркера CSRF. Это часто проще, поскольку многие JavaScript-фреймворки предоставляют крючки, которые позволяют устанавливать заголовки при каждом запросе.
Сначала необходимо получить токен CSRF. Как это сделать, зависит от того, включены ли параметры CSRF_USE_SESSIONS
и CSRF_COOKIE_HTTPONLY
.
Получение маркера, если CSRF_USE_SESSIONS
и CSRF_COOKIE_HTTPONLY
составляют False
¶
Рекомендуемым источником маркера является cookie csrftoken
, который будет установлен, если вы включили защиту CSRF для ваших представлений, как описано выше.
По умолчанию маркер CSRF имеет имя csrftoken
, но вы можете управлять именем cookie с помощью параметра CSRF_COOKIE_NAME
.
Вы можете приобрести токен следующим образом:
function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } const csrftoken = getCookie('csrftoken');
Приведенный выше код можно упростить, используя JavaScript Cookie library для замены getCookie
:
const csrftoken = Cookies.get('csrftoken');
Примечание
Токен CSRF также присутствует в DOM в маскированной форме, но только если он явно включен в шаблон с помощью csrf_token
. Cookie содержит канонический, незамаскированный маркер. CsrfViewMiddleware
будет принимать любой из них. Однако для защиты от атак BREACH рекомендуется использовать маскированный токен.
Предупреждение
Если ваше представление не выводит шаблон, содержащий тег шаблона csrf_token
, Django может не установить куки CSRF-токена. Это часто встречается в случаях, когда формы динамически добавляются на страницу. Для решения этой проблемы Django предоставляет декоратор представления, который принудительно устанавливает cookie: ensure_csrf_cookie()
.
Установка маркера в запросе AJAX¶
Наконец, вам нужно установить заголовок в запросе AJAX. Использование API fetch():
const request = new Request( /* URL */, { method: 'POST', headers: {'X-CSRFToken': csrftoken}, mode: 'same-origin' // Do not send CSRF token to another domain. } ); fetch(request).then(function(response) { // ... });
Использование защиты CSRF в шаблонах Jinja2¶
Бэкенд шаблонов Django Jinja2
добавляет {{ csrf_input }}
в контекст всех шаблонов, что эквивалентно {% csrf_token %}
в языке шаблонов Django. Например:
<form method="post">{{ csrf_input }}
Использование метода декоратора¶
Вместо того чтобы добавлять CsrfViewMiddleware
в качестве абсолютной защиты, вы можете использовать декоратор csrf_protect()
, который обладает точно такой же функциональностью, для определенных представлений, которые нуждаются в защите. Он должен использоваться как для представлений, которые вставляют CSRF-токен в вывод, так и для тех, которые принимают данные POST-формы. (Часто это одна и та же функция представления, но не всегда).
Использование декоратора само по себе не рекомендуется, поскольку если вы забудете его использовать, у вас будет дыра в безопасности. Стратегия «пояса и скобок», при которой используются оба декоратора, вполне подходит, и накладные расходы будут минимальными.
Обработка отклоненных запросов¶
По умолчанию пользователю отправляется ответ „403 Forbidden“, если входящий запрос не проходит проверку, выполняемую CsrfViewMiddleware
. Обычно это происходит только в случае настоящей подделки межсайтовых запросов или когда из-за ошибки программирования маркер CSRF не был включен в форму POST.
Однако страница ошибки не очень дружелюбна, поэтому вы можете захотеть создать собственное представление для обработки этого условия. Для этого установите параметр CSRF_FAILURE_VIEW
.
Сбои CSRF регистрируются как предупреждения в журнале django.security.csrf.
Использование защиты CSRF с кэшированием¶
Если тег шаблона csrf_token
используется шаблоном (или функция get_token
вызывается каким-либо другим способом), CsrfViewMiddleware
добавит cookie и заголовок Vary: Cookie
в ответ. Это означает, что промежуточное ПО будет хорошо взаимодействовать с промежуточным ПО кэша, если оно используется в соответствии с инструкциями (UpdateCacheMiddleware
идет перед всеми другими промежуточными ПО).
Однако, если вы используете декораторы кэша на отдельных представлениях, промежуточное ПО CSRF еще не сможет установить заголовок Vary или куки CSRF, и ответ будет кэширован без них. В этом случае для всех представлений, которые потребуют вставки маркера CSRF, следует сначала использовать декоратор django.views.decorators.csrf.csrf_protect()
:
from django.views.decorators.cache import cache_page from django.views.decorators.csrf import csrf_protect @cache_page(60 * 15) @csrf_protect def my_view(request): ...
Если вы используете представления на основе классов, вы можете обратиться к Decorating class-based views.
Тестирование и защита от CSRF¶
Декоратор CsrfViewMiddleware
обычно сильно мешает тестированию функций представления из-за необходимости использования CSRF-токена, который должен быть отправлен с каждым POST-запросом. По этой причине HTTP-клиент Django для тестов был модифицирован для установки флага в запросах, который ослабляет промежуточное программное обеспечение и декоратор csrf_protect
, так что они больше не отклоняют запросы. Во всех остальных отношениях (например, отправка cookies и т.д.) они ведут себя одинаково.
Если по какой-то причине вы хотите, чтобы тестовый клиент выполнял проверку CSRF, вы можете создать экземпляр тестового клиента, который будет выполнять проверку CSRF:
>>> from django.test import Client >>> csrf_client = Client(enforce_csrf_checks=True)
Краевые случаи¶
Определенные представления могут иметь необычные требования, которые означают, что они не вписываются в обычную схему, предусмотренную здесь. В таких ситуациях может быть полезен ряд утилит. Сценарии, в которых они могут понадобиться, описаны в следующем разделе.
Отключение защиты CSRF только для нескольких просмотров¶
Большинство представлений требуют защиты от CSRF, но некоторые не требуют.
Решение: вместо того чтобы отключать промежуточное ПО и применять csrf_protect
ко всем представлениям, которым оно необходимо, включите промежуточное ПО и используйте csrf_exempt()
.
Установка маркера, когда CsrfViewMiddleware.process_view()
не используется¶
Бывают случаи, когда CsrfViewMiddleware.process_view
может не выполняться до запуска вашего представления — например, обработчики 404 и 500 — но вам все равно нужен CSRF-токен в форме.
Решение: используйте requires_csrf_token()
Включение маркера CSRF в незащищенное представление¶
Могут быть некоторые представления, которые не защищены и были исключены с помощью csrf_exempt
, но все равно должны включать маркер CSRF.
Решение: используйте csrf_exempt()
, за которым следует requires_csrf_token()
. (т.е. requires_csrf_token
должен быть самым внутренним декоратором).
Защита представления только для одного пути¶
Представление нуждается в защите CSRF только при одном наборе условий, и не должно иметь ее в остальное время.
Решение: используйте csrf_exempt()
для всей функции представления, и csrf_protect()
для пути внутри нее, который нуждается в защите. Пример:
from django.views.decorators.csrf import csrf_exempt, csrf_protect @csrf_exempt def my_view(request): @csrf_protect def protected_path(request): do_something() if some_condition(): return protected_path(request) else: do_something_else()
Защита страницы, использующей AJAX без HTML-формы¶
Страница делает POST-запрос через AJAX, и на странице нет HTML-формы с csrf_token
, которая бы вызвала отправку требуемого CSRF-куки.
Решение: используйте ensure_csrf_cookie()
в представлении, которое отправляет страницу.
Защита от CSRF в многократно используемых приложениях¶
Поскольку разработчик может отключить CsrfViewMiddleware
, все соответствующие представления в приложениях contrib используют декоратор csrf_protect
для обеспечения безопасности этих приложений от CSRF. Рекомендуется, чтобы разработчики других многократно используемых приложений, которые хотят получить такие же гарантии, также использовали декоратор csrf_protect
в своих представлениях.