The clickjacking middleware and decorators provide easy-to-use protection against clickjacking. This type of attack occurs when a malicious site tricks a user into clicking on a concealed element of another site which they have loaded in a hidden frame or iframe.
Suppose an online store has a page where a logged in user can click “Buy Now” to purchase an item. A user has chosen to stay logged into the store all the time for convenience. An attacker site might create an “I Like Ponies” button on one of their own pages, and load the store’s page in a transparent iframe such that the “Buy Now” button is invisibly overlaid on the “I Like Ponies” button. If the user visits the attacker’s site, clicking “I Like Ponies” will cause an inadvertent click on the “Buy Now” button and an unknowing purchase of the item.
Modern browsers honor the X-Frame-Options HTTP header that indicates whether or not a resource is allowed to load within a frame or iframe. If the response contains the header with a value of SAMEORIGIN
then the browser will only load the resource in a frame if the request originated from the same site. If the header is set to DENY
then the browser will block the resource from loading in a frame no matter which site made the request.
Django provides a few ways to include this header in responses from your site:
The X-Frame-Options
HTTP header will only be set by the middleware or view decorators if it is not already present in the response.
X-Frame-Options
for all responsesTo set the same X-Frame-Options
value for all responses in your site, put 'django.middleware.clickjacking.XFrameOptionsMiddleware'
to MIDDLEWARE
:
MIDDLEWARE = [ ... 'django.middleware.clickjacking.XFrameOptionsMiddleware', ... ]
This middleware is enabled in the settings file generated by startproject
.
By default, the middleware will set the X-Frame-Options
header to DENY
for every outgoing HttpResponse
. If you want any other value for this header instead, set the X_FRAME_OPTIONS
setting:
X_FRAME_OPTIONS = 'SAMEORIGIN'
When using the middleware there may be some views where you do not want the X-Frame-Options
header set. For those cases, you can use a view decorator that tells the middleware not to set the header:
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.")
Note
If you want to submit a form or access a session cookie within a frame or iframe, you may need to modify the CSRF_COOKIE_SAMESITE
or SESSION_COOKIE_SAMESITE
settings.
X-Frame-Options
per viewTo set the X-Frame-Options
header on a per view basis, Django provides these decorators:
from django.http import HttpResponse from django.views.decorators.clickjacking import xframe_options_deny from django.views.decorators.clickjacking import xframe_options_sameorigin @xframe_options_deny def view_one(request): return HttpResponse("I won't display in any frame!") @xframe_options_sameorigin def view_two(request): return HttpResponse("Display in a frame if it's from the same origin as me.")
Note that you can use the decorators in conjunction with the middleware. Use of a decorator overrides the middleware.
The X-Frame-Options
header will only protect against clickjacking in a modern browser. Older browsers will quietly ignore the header and need other clickjacking prevention techniques.
X-Frame-Options
A complete list of browsers supporting X-Frame-Options
.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/3.2/ref/clickjacking/