點擊劫持保護¶
點擊劫持中間件和裝飾器提供了易於使用的保護,以防範點擊劫持。這種攻擊發生在惡意網站欺騙使用者點擊另一個網站的隱藏元素時,而該網站是以隱藏框架或 iframe 載入的。
點擊劫持的範例¶
假設一家線上商店有一個頁面,已登入的使用者可以點擊「立即購買」來購買商品。為了方便起見,使用者選擇一直保持登入商店。攻擊者網站可能會在他們自己的頁面上建立一個「我喜歡小馬」按鈕,並在透明 iframe 中載入商店的頁面,以便將「立即購買」按鈕不可見地覆蓋在「我喜歡小馬」按鈕上。如果使用者造訪攻擊者的網站,點擊「我喜歡小馬」將會導致無意中點擊「立即購買」按鈕,並在不知情的情況下購買商品。
防止點擊劫持¶
現代瀏覽器會遵循 X-Frame-Options HTTP 標頭,該標頭指示是否允許資源在框架或 iframe 中載入。如果回應包含值為 SAMEORIGIN
的標頭,則瀏覽器只會在請求來自同一個網站時,才會在框架中載入資源。如果標頭設定為 DENY
,則無論哪個網站發出請求,瀏覽器都會阻止資源在框架中載入。
Django 提供了幾種方法將此標頭包含在您網站的回應中
一個在所有回應中設定標頭的中間件。
一組檢視裝飾器,可用於覆寫中間件或僅為特定檢視設定標頭。
如果回應中不存在 X-Frame-Options
HTTP 標頭,則只會由中間件或檢視裝飾器設定。
如何使用¶
為所有回應設定 X-Frame-Options
¶
若要為您網站中的所有回應設定相同的 X-Frame-Options
值,請將 'django.middleware.clickjacking.XFrameOptionsMiddleware'
放入 MIDDLEWARE
MIDDLEWARE = [
...,
"django.middleware.clickjacking.XFrameOptionsMiddleware",
...,
]
此中間件會在 startproject
產生的設定檔中啟用。
預設情況下,中間件會將每個傳出的 HttpResponse
的 X-Frame-Options
標頭設定為 DENY
。如果您希望此標頭有其他值,請設定 X_FRAME_OPTIONS
設定
X_FRAME_OPTIONS = "SAMEORIGIN"
當使用中間件時,可能會有某些檢視您不希望設定 X-Frame-Options
標頭。對於這些情況,您可以使用一個檢視裝飾器,告知中間件不要設定標頭
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.")
注意
如果您想在框架或 iframe 中提交表單或存取會話 Cookie,您可能需要修改 CSRF_COOKIE_SAMESITE
或 SESSION_COOKIE_SAMESITE
設定。
已將對包裝非同步檢視函式的支援新增至 @xframe_options_exempt
裝飾器。
依檢視設定 X-Frame-Options
¶
為了在每個檢視的基礎上設定 X-Frame-Options
標頭,Django 提供了這些裝飾器
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.")
請注意,您可以結合中間件使用裝飾器。使用裝飾器會覆寫中間件。
已將對包裝非同步檢視函式的支援新增至 @xframe_options_deny
和 @xframe_options_sameorigin
裝飾器。
限制¶
X-Frame-Options
標頭僅會在現代瀏覽器中防止點擊劫持。