Django comes with middleware and decorator that allows developers to pervent their site from being attacked by clickjacking. In Clickjacking attack, some other website loads your website inside a iframe and makes users click on any button / element of your website, from their website. This is serious security issue and can lead to a lot of misuse of your website. In this article I'll talk about how Django prevents clickjacking. But first let's take a look at an example of clickjacking.
Example of clickjacking
Suppose you are running a website that has a button for loggend in users to upvote a content they like. Just like we have at HackersFriend. Now, any attacker want to get upvotes on a content. So, he will load the page of your website on their website inside an transparent iframe and show this button as something else, click here to go home. Users at their website will think like they are clicking on home button, while they are actually clicking on upvote button. This way, attacker will get upvotes without users intention.
How to prevent clickjacking
clickjacking has been noticed by major browser providers and to resolve it, they decided to coin X-Frame-Options HTTP header. X-Frame-Options HTTP header has two options that blocks site from being loaded inside a frame or iframe. If your X-Frame-Options HTTP header is set to sameorigin browsers will load your site inside iframe / frame only if that frame exists on your website. Other websites attempting to load your site inside a frame will be blocked by browsers. Also, X-Frame-Options HTTP header if set to deny will not load your site inside any frame at all no matter which site is making request.
In Django, you have 2 ways to include this header into your HTTP requests.
- Use clickjacking middleware - This will set HTTP headers for every HTTP request.
- Use view decorators - These docorators will override existing behaviour (of clickjacking middleware also)
Implementation using clickjacking middlware
In your settings.py file inlcude 'django.middleware.clickjacking.XFrameOptionsMiddleware' in MIDDLEWARE list.
MIDDLEWARE = [ ... 'django.middleware.clickjacking.XFrameOptionsMiddleware', ... ]
After inclusion of this middleware, all the X-Frame-Options HTTP header will be set to DENY if you want to change, sue X_FRAME_OPTIONS in your settings.py file.
X_FRAME_OPTIONS = 'SAMEORIGIN'
To override this behaviour for any specific view you can use @xframe_options_exempt decorator with your view.
from django.http import HttpResponse from django.views.decorators.clickjacking import xframe_options_exempt @xframe_options_exempt def LoadsInIframe(request): return HttpResponse("This will load on any site inside frame")
Implementation per view using decorators
To set X-Frame-Options HTTP header per view you can use @xframe_options_deny and @xframe_options_sameorigin decorator with your views. They are both parts of django.views.decorators.clickjacking.
from django.views.decorators.clickjacking import xframe_options_deny from django.views.decorators.clickjacking import xframe_options_sameorigin from django.http import HttpResponse @xframe_options_deny def NotInsideFrame(request): return HttpResponse("This wont work in any frame!") @xframe_options_sameorigin def GoesInsideFrame(request): return HttpResponse("This will load inside frames of same origin.")
Decorators override the global settings of middleware, so if you have done any setting using clickjacking middleware they will not work on these views.