Django_csrf

 

 

CSRF攻擊介紹

 CSRF 攻擊能夠在受害者絕不知情的狀況下以受害者名義僞造請求發送給受攻擊站點,從而在並未受權的狀況下執行在權限保護之下的操做。好比說,受害者 Bob 在銀行有一筆存款,經過對銀行的網站發送請求 http://bank.example/withdraw?account=bob&amount=1000000&for=bob2 可使 Bob 把 1000000 的存款轉到 bob2 的帳號下。一般狀況下,該請求發送到網站後,服務器會先驗證該請求是否來自一個合法的 session,而且該 session 的用戶 Bob 已經成功登錄。黑客 Mallory 本身在該銀行也有帳戶,他知道上文中的 URL 能夠把錢進行轉賬操做。Mallory 能夠本身發送一個請求給銀行:http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory。可是這個請求來自 Mallory 而非 Bob,他不能經過安全認證,所以該請求不會起做用。這時,Mallory 想到使用 CSRF 的攻擊方式,他先本身作一個網站,在網站中放入以下代碼: src=」http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory 」,而且經過廣告等誘使 Bob 來訪問他的網站。當 Bob 訪問該網站時,上述 url 就會從 Bob 的瀏覽器發向銀行,而這個請求會附帶 Bob 瀏覽器中的 cookie 一塊兒發向銀行服務器。大多數狀況下,該請求會失敗,由於他要求 Bob 的認證信息。可是,若是 Bob 當時恰巧剛訪問他的銀行後不久,他的瀏覽器與銀行網站之間的 session 還沒有過時,瀏覽器的 cookie 之中含有 Bob 的認證信息。這時,悲劇發生了,這個 url 請求就會獲得響應,錢將從 Bob 的帳號轉移到 Mallory 的帳號,而 Bob 當時絕不知情。等之後 Bob 發現帳戶錢少了,即便他去銀行查詢日誌,他也只能發現確實有一個來自於他本人的合法請求轉移了資金,沒有任何被攻擊的痕跡。而 Mallory 則能夠拿到錢後逍遙法外。html

 

Django設置CSRF防禦

全局

中間件 django.middleware.csrf.CsrfViewMiddleware

局部

from django.views.decorators.csrf import csrf_exempt,csrf_protect


@csrf_protect,爲當前函數強制設置防跨站請求僞造功能,即使settings中沒有設置全局中間件。

@csrf_exempt,取消當前函數防跨站請求僞造功能,即使settings中設置了全局中間件。
# FBV
@csrf_exempt
def index(request):
    if request.method == "POST":
        return HttpResponse("POST 200")


# CBV
# 方法1
urlpatterns = [
    re_path("index/$",csrf_exempt(views.Index.as_view())),
]

# 方法2 在dispatch添加@csrf_exempt/protect
class Index(View):
        # @csrf_exempt  此爲無效,需在dispatch添加
    def post(self,request):
        print(request.method)
        print(request.POST)
        print(request.body)
        return HttpResponse("200 OK")

    # @csrf_exempt  此爲無效,需在dispatch添加
    def patch(self,request):
        print(request.method)
        print(request.body)
        print(request.method)
        return HttpResponse("patch 200 ok")

    # @csrf_exempt  此爲無效,需在dispatch添加
    def put(self,request):
        print(request.method)
        print(request.body)
        print(request.method)
        return HttpResponse("put 200 ok")

    @csrf_exempt
    def dispatch(self, request, *args, **kwargs):
        print("dispatch before")
        ret = super(Index, self).dispatch(request,*args,**kwargs)
        print("dispatch after")
        return ret
使用

HTML發送CSRF

1、    csrf在ajax提交的時候經過請求頭傳遞的給後臺的

二、    csrf在前端的key爲:X-CSRFtoken,到後端的時候django會自動添加HTTP_,而且最後爲HTTP_X_CSRFtoken

三、    csrf在form中提交的時須要在前端form中添加{%csrftoken%}

form表單提交

在form表單裏面須要添加{%csrf_token%}

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="">
    {% csrf_token %}


    <div>username: <input type="text" name="username"></div>
    <div>password: <input type="password" name="password"></div>
    <input type="submit">
</form>
    <div><h3>這是csrf_token的值</h3>{{ csrf_token }}</div>

</body>
</html>
舉例

 

AJAX提交

由於cookie中一樣存在csrftoken,因此能夠在js中經過:

$.cookie("csrftoken")獲取:  headers:{ "X-CSRFtoken":$.cookie("csrftoken")},

或者
{{ csrf_token }}: data:{"usr":"root","pwd":"123","csrfmiddlewaretoken":"{{csrf_token}}"},
若是經過ajax進行提交數據,這裏提交的csrftoken是經過請求頭中存放,須要提交一個字典類型的數據,即這個時候須要一個key。

在views中的login函數中:from django.conf import settings,而後打印print(settings.CSRF_HEADER_NAME)

這裏須要注意一個問題,這裏導入的settings並非咱們在項目文件下看到的settings.py文件,這裏是是一個全局的settings配置,而當咱們在項目目錄下的settings.py中配置的時候,咱們添加的配置則會覆蓋全局settings中的配置

print(settings.CSRF_HEADER_NAME)打印的內容爲:HTTP_X_CSRFTOKEN

這裏的HTTP_X_CSRFTOKEN是django在X_CSRF的前面添加了HTTP_,因此實際傳遞的是就是X_CSRFtoken,而在前端頁面的ajax傳遞的時候因爲不能使用下劃線因此傳遞的是X_CSRFtoken
說明

 

示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{#<form action="">#}
{#    {% csrf_token %}#}
{##}
{##}
{#    <div>username: <input type="text" name="username"></div>#}
{#    <div>password: <input type="password" name="password"></div>#}
{#    <input type="submit">#}
{#</form>#}
{#    <div><h3>這是csrf_token的值</h3>{{ csrf_token }}</div>#}

<input type="button" id="btn1" value="btn1">
<input type="button" id="btn2" value="btn2">

<script src="/static/jquery.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script>
    $("#btn1").click(function () {
        $.ajax({
            url:"/app01/index.html",
            type:"POST",
            data:{"usr":"root","pwd":"123","csrfmiddlewaretoken":"{{csrf_token}}"},
            success:function (arg) {
                console.log("btn1")
            }
        })
    });
    $("#btn2").click(function () {
        $.ajax({
            url:"/app01/index.html",
            type:"POST",
            data:{"usr":"root","pwd":"123"},
            headers:{ "X-CSRFtoken":$.cookie("csrftoken")},
            success:function (arg) {
                console.log("btn2")
            }
        })
    })
</script>
</body>
</html>
"X-CSRFtoken":$.cookie("csrftoken") 以及 "csrfmiddlewaretoken":"{{csrf_token}}"
def index(request):
    if request.method == "GET":
        print(settings.CSRF_HEADER_NAME)  # HTTP_X_CSRFTOKEN
        return render(request,"index.html")
    elif request.method == "POST":
        print(request.POST)
        print(request.body)
        return HttpResponse("HH")
views.py

 

 

參考or轉發

http://www.javashuo.com/article/p-xcptltgl-cn.html前端

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息