I am trying test some of the post methods in my Django app, but due to the csrf_token, I can not test it without a browser. So I used
#csrf_exempt decorator
However I forget to remove those decorators in production. Is there a better way like this?
#csrf_exempt(in_debug_only=True)
So like this decorator is active only when the application is in debug mode. Or is there a better way to test post requests?
Like selenium might have some methods to do that?
Note: I m currently using Django 1.7.2 and Python 3.4.1
Inspired by this answer:
You can add a new file to your app, let's call it disable_csrf.py:
class DisableCSRF(object):
def process_request(self, request):
setattr(request, '_dont_enforce_csrf_checks', True)
Then you can edit your settings.py to add this:
if DEBUG:
MIDDLEWARE_CLASSES += myapp.disable.DisableCSRF
Let me know if it worked.
Related
I'm trying to enable django to allow one specific view to be embedded on external sites, preferabilly without sites restrictions.
In my views.py file, I have added the following code, where the view futurebig is the one I want to enable to be embedded:
from django.views.decorators.clickjacking import xframe_options_sameorigin
...
#xframe_options_sameorigin
def futurebig(request):
...
return render_to_response('templates/iframe/future_clock_big.html', context_dict, context)
which doesn't help as I understand because it only enables embedding in the same server.
How can I set the headers for that specific view to enable it to be embedded in any website?
For the record, I'm just a frontend developer, the backend developer who developed the site is no longer working with me and refused to document his code, so, If anyone could help me and explain carefully where and what modifications I should do, I'll apreciatte it very much.
Thanks.
As far as I know, the Django version is 1.6
You are going in the right direction, but exact decorator which you will need to achieve this is 'xframe_options_exempt'.
from django.http import HttpResponse
from django.views.decorators.clickjacking import xframe_options_exempt
#xframe_options_exempt
def ok_to_load_in_a_frame(request):
return HttpResponse("This page is safe to load in a frame on any site.")
PS: DJango 1.6 is no longer supported. It is good time to get an upgrade.
Apparently you can set a rule in your settings telling the following:
X_FRAME_OPTIONS = 'ALLOW-FROM https://example.com/'
Also nowadays you should consider moving to CSP
Content-Security-Policy: frame-ancestors 'self' example.com *.example.net ;
See https://stackoverflow.com/a/25617678/186202
If you want to allow the frame in specific view you can add Content-Security-Policy to your view response, so your code will be something like this
def MyView(request):
....
....
response = render(request,'MyViewHtml.html' ,{...})
response ['Content-Security-Policy'] = "frame-ancestors 'self' https://example.com"
I'm trying to enable django to allow one specific view to be embedded on external sites, preferabilly without sites restrictions.
In my views.py file, I have added the following code, where the view futurebig is the one I want to enable to be embedded:
from django.views.decorators.clickjacking import xframe_options_sameorigin
...
#xframe_options_sameorigin
def futurebig(request):
...
return render_to_response('templates/iframe/future_clock_big.html', context_dict, context)
which doesn't help as I understand because it only enables embedding in the same server.
How can I set the headers for that specific view to enable it to be embedded in any website?
For the record, I'm just a frontend developer, the backend developer who developed the site is no longer working with me and refused to document his code, so, If anyone could help me and explain carefully where and what modifications I should do, I'll apreciatte it very much.
Thanks.
As far as I know, the Django version is 1.6
You are going in the right direction, but exact decorator which you will need to achieve this is 'xframe_options_exempt'.
from django.http import HttpResponse
from django.views.decorators.clickjacking import xframe_options_exempt
#xframe_options_exempt
def ok_to_load_in_a_frame(request):
return HttpResponse("This page is safe to load in a frame on any site.")
PS: DJango 1.6 is no longer supported. It is good time to get an upgrade.
Apparently you can set a rule in your settings telling the following:
X_FRAME_OPTIONS = 'ALLOW-FROM https://example.com/'
Also nowadays you should consider moving to CSP
Content-Security-Policy: frame-ancestors 'self' example.com *.example.net ;
See https://stackoverflow.com/a/25617678/186202
If you want to allow the frame in specific view you can add Content-Security-Policy to your view response, so your code will be something like this
def MyView(request):
....
....
response = render(request,'MyViewHtml.html' ,{...})
response ['Content-Security-Policy'] = "frame-ancestors 'self' https://example.com"
I am trying to set my Django app work with multiple domains (while serving slightly different content)
I wrote this middleware:
class MultiSiteMiddleware(object):
def process_request(self, request):
host = request.get_host()
host_part = host.split(':')[0].split('.com')[0].split('.')
host = host_part[len(host_part)-1] + '.com'
site = Site.objects.get(domain=host)
settings.SITE_ID = site.id
settings.CURRENT_HOST = host
Site.objects.clear_cache()
return
In views I use this:
def get_site(request):
current_site = get_current_site(request)
return current_site.name
def view(request, pk):
site = get_site(request)
if site == 'site1':
# serve content1
...
elif site == 'site2'
# serve content2
...
But now there are 404 errors (I sometimes find them in logs, don't see them while browsing my site manually) where they aren't supposed to be, like my site sometimes is serving content for wrong domains, can they happen because of some flaw in the above middleware and view code or I should look somewhere else?
I had a similar requirement and decided not to use the django sites framework. My middleware looks like
class MultiSiteMiddleware(object):
def process_request(self, request):
try:
domain = request.get_host().split(":")[0]
request.site = Site.objects.get(domain=domain)
except Site.DoesNotExist:
return http.HttpResponseNotFound()
then my views have access to request.site
If you're seeing 404's for sites that aren't yours in your logs it would seem like somebody has pointed their domain at your servers IP address, you could use apache/nginx to filter these out before they hit your app, but your middleware should catch them (though possibly by raising an uncaught 500 error instead of a 404)
Serve multiple domain from one website (django1.8 python3+)
The goal is, obviously, to serve multiple domains, from one Django instance. That means, we use the same models, the same database, the same logic, the same views, the same templates, but to serve different things.
Searching the interwebs, I came to the idea of using the sites framework. The sites framework was designed to do exactly that thing. In fact, the sites framework has been used to do exactly that. But I haven't been able to know on which version of Django it was, and actually, I came to the idea the sites framework was just a vestigial module. Basically, it is just a table, with SITE_ID and SITE_URL, that you can easily access with a function. But I've been unable to find how, from that, you can do a multi-domain website.
So my idea has been, how to modify the url resolver. The idea behind all these is easy : www.domain1.com/bar is resolved to /domain1/bar, and www.domain2.foo is resolved to /domain2/foo. This solves the problem because, if you want to serve multiple domains, you just have to serve multiple folders.
In Django, to achieve this, you have to modify two things :
* the way Django routes requests
* the way django write urls
The way Django routes requests
Django routes requests with middlewares. That's it. So we just have to write a middleware that re-route requests.
To make it easier, middlewares can have a process_request method that process requests (WOW), before requests are handled. So let's write a DomainNameMiddleware
#!python
#app/middleware.py
class DomaineNameMiddleware:
"""
change the request path to add the domain_name at the first
"""
def process_request(self, request):
#first, we split the domain name, and take the part before the extension
request_domain = request.META['HTTP_HOST'].split('.')[-2]
request.path_info = "/%s/%s" % (request_domain, request.path.split('/')[1:])
The way Django writes URL
When I'm talking about django writing url, i'm principally thinking of the {% url %} template tag, the get_absolute_url methods, the resolve and resolve_lazy functions, and those basic Django thing. If we rewrite the way Django handle url, we have to tell Django to write url that way.
But basically it's pretty easy, thanks to Django.
You can easily rewrite basic Django function by just rewriting them, typically in init.py files of modules you added as apps. So :
#!python
#anyapp/__init__.py
from django.core import urlresolvers
old_reverse = urlresolvers.reverse
def new_reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None):
"""
return an url with the first folder as a domain name in .com
"""
TLD = 'com'
old_reverse_url = old_reverse(viewname, urlconf, args, kwargs, current_app)
# admin will add itself everytime you reload an admin page, so we have to delete it
if current_app == 'admin':
return '/%s' % old_reverse_url[len('admin'):].replace('adminadmin', 'admin')
return '//%s.%s/%s' % (app, TLD, path)
How to use it ?
I use it with base urls.py as dispatchedr.
#!python
#urls.py
from django.conf.urls import include, url
from domain1 import urls as domain1_urls
from domain2 import urls as domain2_urls
urlpatterns = [
url(r'^domain1/', include(domain1_urls, namespace='domain1')),
url(r'^domain2/', include(domain2_urls, namespace='domain2)),
]
Django's Sites framework has built-in middleware to accomplish this.
Simply enable the Sites framework and add this to your MIDDLEWARE:
'django.contrib.sites.middleware.CurrentSiteMiddleware'
This automatically passes a request object to Site.objects.get_current() on every request. It solves your problem by giving you access to request.site on every request.
For reference, the code as of 1.11 is:
from django.utils.deprecation import MiddlewareMixin
from .shortcuts import get_current_site
class CurrentSiteMiddleware(MiddlewareMixin):
"""
Middleware that sets `site` attribute to request object.
"""
def process_request(self, request):
request.site = get_current_site(request)
I will suggest you to use django-multisite .It will fulfill your requirement.
Try using the "sites" framework in django to get the domain name. You already know this I guess.
Take a look here: https://docs.djangoproject.com/en/1.7/ref/contrib/sites/#getting-the-current-domain-for-full-urls
See this:
>>> Site.objects.get_current().domain
'example.com'
Without the https://www or http://www.. Probably your domains will end in .org or some country .pe .ru etc not just .com.
There might be a case when people don't point to your domain but to your IP address for some reason, maybe development of testing so you should always raise an exception with Site.DoesNotExist
I am trying to create a simple, html-only facebook app for a client's fb page. I would like to use django's flatpages so that the client and his staff can change the content of the app through the django admin of their site. The problem is that Django returns a 403 "CSRF verification failed. Request aborted." error when facebook attempts to send its own POST info and access the url of the app.
I already know about the #csrf_exempt decorator, but I am not sure how I would apply it to the flatpage view, as it is within the django.contrib code. Furthermore I would only want to disable csrf protection when the view is asked to call a specific facebook.html template (not not the default.html template). If there happened to be a {% crsf_exempt %} template tag for example, that would be perfect.
Can anyone think of a way to resolve this problem? Or maybe I should give up on the idea of using the django-flatpages to serve the facebook app?
Try using this decorator on your views that are called facebook:
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
this will disable csrf protection on that view.
Does this help?
I ran into the exact same problem as you. I wanted to diable csrf for flatpages (but not for the rest of the site) and ended up with the following middleware:
class DisableCSRFOnFlatPages(object):
def process_request(self, request):
try:
FlatPage.objects.get(url=request.META.get('PATH_INFO'))
setattr(request, '_dont_enforce_csrf_checks', True)
except FlatPage.DoesNotExist:
return
Add it to your settings and it should disable the csrf check whenever there's a flatpage.
The django csrf middleware can't be disabled. I've commented it out from my Middleware of my project but my logins are failing due to missing CSRF issues. I'm working from the Django trunk. How can CSRF cause issues if it is not enabled in middleware?
I have to disable it because there are lots of POST requests on my site that CSRF just breaks. Any feedback on how I can completely disable CSRF in a django trunk project?
The "new' CSRF framework from Django's trunk is also breaking an external site that is coming in and doing a POST on a URL I'm giving them (this is part of a restful API.) I can't disable the CSRF framework as I said earlier, how can I fix this?
Yes, Django csrf framework can be disabled.
To manually exclude a view function from being handled by any CSRF middleware, you can use the csrf_exempt decorator, found in the django.views.decorators.csrf module. For example: (see doc)
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def my_view:
return Httpresponse("hello world")
..and then remove {% csrf_token %} inside the forms from your template,or leave other things unchanged if you have not included it in your forms.
You can disable this in middleware.
In your settings.py add a line to MIDDLEWARE_CLASSES:
MIDDLEWARE_CLASSES = (
myapp.disable.DisableCSRF,
)
Create a disable.py in myapp with the following
class DisableCSRF(object):
def process_request(self, request):
setattr(request, '_dont_enforce_csrf_checks', True)
Basically if you set the _dont_enforce_csrf_checks in your request, you should be ok.
See answers below this for a better solution. Since I wrote this, a lot has changed. There are now better ways to disable CSRF.
I feel your pain. It's not acceptable for a framework to change such fundamental functionality. Even if I want to start using this from now on, I have legacy sites on the same machine sharing a copy of django. Changes like this should require major version number revisions. 1.x --> 2.x.
Anyway, to fix it I just commented it out and have stopped updating Django as often.
File: django/middleware/csrf.py
Around line 160:
# check incoming token
# request_csrf_token = request.POST.get('csrfmiddlewaretoken', None)
# if request_csrf_token != csrf_token:
# if cookie_is_new:
# # probably a problem setting the CSRF cookie
# return reject("CSRF cookie not set.")
# else:
# return reject("CSRF token missing or incorrect.")
In general, you shouldn't be disabling CSRF protection, since doing so opens up security holes. If you insist, though…
A new way of doing CSRF protection landed in trunk just recently. Is your site by chance still configured to do it the old way? Here are the docs for The New Way™ and here are the docs for The Old Way™.
I simply tried removing the references to csrf middleware classes from my settings.py, it worked. Not sure if this is acceptable. Any comments?
Below two lines were removed -
'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.csrf.CsrfResponseMiddleware',
my django version is 1.11. the middleware should be like this:
from django.utils.deprecation import MiddlewareMixin
class DisableCSRF(MiddlewareMixin):
def process_request(self, request):
setattr(request, '_dont_enforce_csrf_checks', True)