I am working on a dJango web and follow the tutorial to protect it against CSRF, I did something and not sure is it write now install or not, how can I see or check it?
From the docs, to enable CSRF protection for your views, follow these steps:
Add the middleware 'django.middleware.csrf.CsrfViewMiddleware' to your list of middleware classes, MIDDLEWARE_CLASSES in your settings.py. (It should come before any view middleware that assume that CSRF attacks have been dealt with.)
In any template that uses a POST form, use the csrf_token tag inside the element if the form is for an internal URL, e.g.:
<form action="." method="post">{% csrf_token %}
In the corresponding view functions, ensure that the 'django.core.context_processors.csrf' context processor is being used.
Following these steps will check that CSRF tokens are included properly.
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.
See the Docs for more info.
Check the MIDDLEWARE_CLASSES tuple in settings.py contains this
'django.middleware.csrf.CsrfViewMiddleware',
If this is there in the tuple , then csrf is installed.
Some like this:
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
# Uncomment the next line for simple clickjacking protection:
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
Related
I have hosted a website at http://cognezic-dev.ap-south-1.elasticbeanstalk.com/login/. On closer inspection, the form has the same csrf token across page refreshes and browsers, which I suspect to be the cause of the issue,this works fine on the local django server.Dont know where this is being cached. I have added CSRF Middleware in the settings.py too.
You can use the test credentials as username bismeet and password bis12345 for testing.
I have also tried creating a custom middleware as follows:
from django.middleware.csrf import rotate_token, CsrfViewMiddleware
from django.utils.deprecation import MiddlewareMixin
class CSRFRefresh(CsrfViewMiddleware,MiddlewareMixin):
def process_response(self, request, response):
print("Custom MiddleWare called")
rotate_token(request)
return response
But it still fails.
My settings.py with custom middleware contains:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'solvesto.middleware.csrf_refresh.CSRFRefresh'
]
If not using the custom middleware,I use:
'django.middleware.csrf.CsrfViewMiddleware'
instead of
'solvesto.middleware.csrf_refresh.CSRFRefresh'
The only last resort I see to make this work is to remove csrf altogether,which is of course,bad for security.
I removed the csrf security,no other solution,works now.
when I try to login using a browser it works correctly but, when I try to user Postman to post username & password it throws csrf token error.
urlpatterns = [
path('', include('rest_framework.urls')),
.......
]
Middlewares
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
]
When I access the api from a browser is allows me to log in.
Currently not using any Permission classes and authentication_classes.
but tested with rest_framework_simplejwt.authentication.JWTAuthentication at the begining.
Currently not using any.
By default, Django needs the crsf_token in all the submitted forms to any views to ensure that the request comes from a legitimate place, so there are several questions here:
1) Why it works from the browser?
Probably, this is because you have a line {% csrf_token %} in your template.html after the <form> tag. This is the way to say to django that it must include a cookie called 'csrf_token' when returning the rendered template. So, when the form is submitted, it takes the cookie 'csrf_token' and includes it in the POST request. When the request is in the server side, django checks that the csrf_token is in the request header and allows the request to continue normally.
This is done automatically and you don't need to care about it only if you include the line {% csrf_token %} after the <form> tag.
2) Why it does not work from postman?
When you send a post from postman, you're not sending the csrf_token in the requests header but you only send the {'username': 'user', 'password': 'pass'} and django rejects the requests since it has no way to know that the request come from a trustworthy place.
3) How can you make the login work from postman?
I see 2 options here.
You can first execute a GET to the login template from postman, and you will see that it returns a cookie called csrf_token. Then you can copy that cookie to include it in your request header. (You can configure postman to save the cookie headers and use them in future requests)
You can use the decorator #csrf_exempt in your view to say django not to check the csrf_token for any view. Here is more info about it https://docs.djangoproject.com/en/3.1/ref/csrf/
But I would not recommend do this in a login view since it could cause that any login request will be accepted regardless of its origin, causing strongly insecure platforms.
I am using this middleware to redirect all pages to a landing page: (part of AuthRequiredMiddleware class.
def process_request(self, request):
assert hasattr(request, 'user')
if not request.user.is_authenticated():
path = request.path_info.lstrip('/')
if path not in ['ipn/', 'pp_cancel/', 'pp_success/', 'sitemap/', 'welcome/']:
lang = request.GET.get('lang', 'en')
ru = request.GET.get('ru', '')
return render_to_response('landing_en.html', RequestContext(request, {'ru': ru}))
and this is my settings.py
MIDDLEWARE_CLASSES = (
'django.middleware.cache.UpdateCacheMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'main.common.SessionBasedLocaleMiddleware.SessionBasedLocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'main.common.tz_middleware.TimezoneMiddleware',
'main.common.sslMiddleware.SSLRedirect',
'main.common.RedirectAllMiddleware.AuthRequiredMiddleware',
)
if the url is (for example) /welcome/ and no redirection is performed {% csrf_token %} works and shows in the form. If user is redirected no csrf_token is shown in the form.
What am I doing wrong?
From the wiki page about CSRF:
Cross-site request forgery, also known as a one-click attack or
session riding [...] is a type of malicious exploit of a website
whereby unauthorized commands are transmitted from a user that the
website trusts.
and later, under prevention:
Verifying that the request's header contains a X-Requested-With (used
by Ruby on Rails before v2.0 and Django before v1.2.5), or checking
the HTTP Referer header and/or HTTP Origin header.
So actually, your csrf protection is working well. Because, while I'm not 100% that the problem is specifically the missing referrer, I do think that it's caused by not using a proper redirect which triggers a csrf violation.
The solution - use HttpResponseRedirect and pass the information to the other view. You can pass it as GET data:
d = {'ru': ru, 'other': 'variables'}
url = '/landing/?%' % '&'.join( map(lambda x: '='.join(x), d.items()) )
return HttpResponseRedirect(url)
You can also use regex patterns in the urls (if that makes sense) or use sessions if there's anything sensitive in there.
I have been trying to set up CSRF protection on my POST forms on my django 1.4.3 site and have been getting the 403 CSRF cookie not set error.
I believe I have followed the doc in detail, followed advice on many forums but all to no avail. I have stripped back the code as much as possible and the cookie just does not set. The csrfmiddlewaretoken is present, so that's not the source of the problem. I'm at my wit's end. No doubt the answer is stupidly simple, I just need a fresh set of eyes to point it out to me...
So here's some code:
#urls.py
...
url(r'^csrf/$', csrf_test, name='csrf_test'),
...
#views.py
...
from django.views.decorators.csrf import csrf_protect
#csrf_protect
def csrf_test(request):
c = {}
c.update(csrf(request))
return render_to_response('csrf.html', c)
...
<!-- csrf.html -->
<html>
<body>
<form action="" method="post">
{% csrf_token %}
<input name="Submit" value="Submit" type="submit"/>
</form>
</body>
</html>
#settings.py
...
MIDDLEWARE_CLASSES = (
'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
#for db transactions. Check middleware order if faulty
'django.middleware.transaction.TransactionMiddleware',
# Uncomment the next line for simple clickjacking protection:
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'debug_toolbar.middleware.DebugToolbarMiddleware',
)
...
TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + (
'django.core.context_processors.csrf',
'django.core.context_processors.request',
)
...
I am running the django development server on 127.0.0.1:8000.
I have cookies enabled on my browsers and have confirmed cookies are being set from other websites.
I have checked the csrfmiddlewaretoken is being passed as a POST variable.
I always get the error, this is not intermittent.
I have no problem with POST forms when I have disabled the middleware/used #csrf_exempt.
As I say, I'm at my wit's end. What on earth have I missed?
Thanks
Nathan
EDIT:
It now works, but I have no idea what has changed. For anyone reading this in the future I created a new project and app, it created the cookie straight away. Thinking it must have been a settings issue I changed the order of my MIDDLEWARE_CLASSES entries by moving 'django.middleware.csrf.CsrfViewMiddleware' down below 'django.contrib.sessions.middleware.SessionMiddleware'. I ran the original app and it worked. However to test whether the settings change was responsible I reversed the change. It still worked. Go figure.
I hope this helps someone in the future FWIW.
Nathan
if you're using render_to_response then you should probably use a RequestContext
This will handle the csrf protection for you -
def csrf_test(request):
render_to_response('csrf.html', context_instance=RequestContext(request))
You don't need to include the csrf_protect decorator, since you've got the csrf middleware.
def csrf_test(request):
.....
return render(request, 'csrf.html', { ..... })
I am with some trouble in Django...
After login I am losing auth session for some pages.
If I access "accounts/login/","accounts/logout/",""accounts/register/" the session always will be there, but if I access different page I cant access the user variable.
This is strange because I am using the same "base.html" for all pages and inside has the logic "if user.is_authenticated", how I said this condition is true just when I access pages that have "accounts" in the URL.
in the settings file I enabled theses three middleware:
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
)
Thanks
Just a guess here: are you including RequestContext in your context in the views that you cannot access user?
In other words, if you call generic views the RequestContext is automatically included but if you are using render_to_response() then you need to call it like this:
return render_to_response('template_name',
{ your context dict },
context_instance=RequestContext(request))