Clickjacking Protection

The clickjacking middleware and decorators provide easy-to-use protectionagainst clickjacking. This type of attack occurs when a malicious sitetricks a user into clicking on a concealed element of another site which theyhave loaded in a hidden frame or iframe.

An example of clickjacking

Suppose an online store has a page where a logged in user can click “Buy Now” topurchase an item. A user has chosen to stay logged into the store all the timefor convenience. An attacker site might create an “I Like Ponies” button on oneof their own pages, and load the store’s page in a transparent iframe such thatthe “Buy Now” button is invisibly overlaid on the “I Like Ponies” button. If theuser visits the attacker’s site, clicking “I Like Ponies” will cause aninadvertent click on the “Buy Now” button and an unknowing purchase of the item.

Preventing clickjacking

Modern browsers honor the X-Frame-Options HTTP header that indicates whetheror not a resource is allowed to load within a frame or iframe. If the responsecontains the header with a value of SAMEORIGIN then the browser will onlyload the resource in a frame if the request originated from the same site. Ifthe header is set to DENY then the browser will block the resource fromloading in a frame no matter which site made the request.

Django provides a few ways to include this header in responses from your site:

  • A middleware that sets the header in all responses.
  • A set of view decorators that can be used to override the middleware or toonly set the header for certain views.The X-Frame-Options HTTP header will only be set by the middleware or viewdecorators if it is not already present in the response.

How to use it

Setting 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' toMIDDLEWARE:

  1. MIDDLEWARE = [
  2. ...
  3. 'django.middleware.clickjacking.XFrameOptionsMiddleware',
  4. ...
  5. ]

This middleware is enabled in the settings file generated bystartproject.

By default, the middleware will set the X-Frame-Options header toDENY for every outgoing HttpResponse. If you want any other value forthis header instead, set the X_FRAME_OPTIONS setting:

  1. X_FRAME_OPTIONS = 'SAMEORIGIN'

Changed in Django 3.0:The default value of the X_FRAME_OPTIONS setting was changedfrom SAMEORIGIN to DENY.

When using the middleware there may be some views where you do not want theX-Frame-Options header set. For those cases, you can use a view decoratorthat tells the middleware not to set the header:

  1. from django.http import HttpResponse
  2. from django.views.decorators.clickjacking import xframe_options_exempt
  3.  
  4. @xframe_options_exempt
  5. def ok_to_load_in_a_frame(request):
  6. return HttpResponse("This page is safe to load in a frame on any site.")

Setting X-Frame-Options per view

To set the X-Frame-Options header on a per view basis, Django provides thesedecorators:

  1. from django.http import HttpResponse
  2. from django.views.decorators.clickjacking import xframe_options_deny
  3. from django.views.decorators.clickjacking import xframe_options_sameorigin
  4.  
  5. @xframe_options_deny
  6. def view_one(request):
  7. return HttpResponse("I won't display in any frame!")
  8.  
  9. @xframe_options_sameorigin
  10. def view_two(request):
  11. 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 ofa decorator overrides the middleware.

Limitations

The X-Frame-Options header will only protect against clickjacking in amodern browser. Older browsers will quietly ignore the header and need otherclickjacking prevention techniques.

Browsers that support X-Frame-Options

  • Internet Explorer 8+
  • Edge
  • Firefox 3.6.9+
  • Opera 10.5+
  • Safari 4+
  • Chrome 4.1+

See also

A complete list of browsers supporting X-Frame-Options.