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 responses¶To 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 view¶To 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.
déc. 04, 2023