1. 程式人生 > >Django:模板template(二)

Django:模板template(二)

無法 size type 查看源碼 隨機生成 ins cli 跨域 一個

將跨站請求偽造和驗證碼的東西記一下

CSRF

Cross Site Request Forgery。跨站請求偽造

鏈接:GET請求;表單:POST請求

某些惡意的網站上,包含鏈接、表單、按鈕、JavaScript。利用用戶在瀏覽器上的認證信息試圖在網站上完成某些操作,稱為CSRF(跨站請求偽造)

例子:

設計兩個頁面,一個用於提交請求(POST),一個用於展示請求提交的數據

booktest/urls.py

urlpatterns = [
    url(^csrf1$,views.csrf1, name="csrf1"),
    url(^csrf2$,views.csrf2, name="
csrf2"), ]

booktest/views.py

def csrf1(request):
    context = {}
    return render(request, booktest/csrf1.html, context)

def csrf2(request):
    uname = request.POST[uname]
    context = {uname: uname}
    return render(request, booktest/csrf2.html, context)

templates/booktest/csrf1.html

<body>
    <form method="post" action="/booktest/csrf2">
        <input type="text" name="uname"/>
        <input type="submit" value="提交"/>
    </form>
</body>

templates/booktest/csrf2.html

<body>
    {{ uname }}
</body>

技術分享圖片

輸入姓名,點擊提交按鈕,會出現如下效果

技術分享圖片

出現這個是因為django默認使用了

CSRF的認證。把Django中的CSRF功能關閉

django4/settings.py

MIDDLEWARE_CLASSES = (
    django.contrib.sessions.middleware.SessionMiddleware,
    django.middleware.common.CommonMiddleware,
    #‘django.middleware.csrf.CsrfViewMiddleware‘,
    django.contrib.auth.middleware.AuthenticationMiddleware,
    django.contrib.auth.middleware.SessionAuthenticationMiddleware,
    django.contrib.messages.middleware.MessageMiddleware,
    django.middleware.clickjacking.XFrameOptionsMiddleware,
    django.middleware.security.SecurityMiddleware,
)

技術分享圖片

改成發布模式

django4/settings.py

DEBUG = False

ALLOWED_HOSTS = [*]

然後,啟動服務器。需要帶上IP地址

python manage.py runserver 192.168.30.2:8080

此時,在瀏覽器上訪問服務器的時候,輸入的URLhttp://192.168.30.2:8080/booktest/csrf1

註意:現在是真實訪問服務器的場景。

任意提交數據,都可以在csrf2中顯示(比如嵌入一段html代碼)

<script>
for(;;) alert(123);
</script>

另外,還有一種可能。現在訪問服務器上的URL http://192.168.30.2:8080/booktest/csrf1 獲得一個網頁的時候,可以把網頁的源碼摳下來。

MIDDLEWARE_CLASSES = (
    django.contrib.sessions.middleware.SessionMiddleware,
    django.middleware.common.CommonMiddleware,
    django.middleware.csrf.CsrfViewMiddleware,
    django.contrib.auth.middleware.AuthenticationMiddleware,
    django.contrib.auth.middleware.SessionAuthenticationMiddleware,
    django.contrib.messages.middleware.MessageMiddleware,
    django.middleware.clickjacking.XFrameOptionsMiddleware,
    django.middleware.security.SecurityMiddleware,
)

但是禁止了CSRF結果就會連自己都無法訪問了(http://192.168.30.2:8080/booktest/csrf1 )所以不能這樣做。

防止跨域攻擊的方法:在csrf1.html中,在表單中添加一個標簽

<body>
    <form method="post" action="/booktest/csrf2">
        {% csrf_token %}
        <input type="text" name="uname"/>
        <input type="submit" value="提交"/>
    </form>
</body>

此時,訪問http://192.168.30.2:8080/booktest/csrf1 的時候,查看源碼,會發現表單中多了一項

技術分享圖片

這個就是CSRF的保護措施了

此時,只有在服務器的URL http://192.168.30.2:8080/booktest/csrf1 http://192.168.30.2:8080/booktest/csrf2 發送請求,才能接收。而在本地的URL file:///D:/gz1833_python/20180918/test.html http://192.168.30.2:8080/booktest/csrf2 發送請求,則會有403的錯誤(Forbidden CSRF verification failed)。

技術分享圖片

驗證碼

技術分享圖片

驗證碼的作用:防爬蟲、減輕服務器的壓力、防CSRF

原理:畫一張圖。圖片上隨機輸出幾個字。要求登錄的人輸入值要和圖片隨機生成的值一致

首先,我們要讓服務器返回一張圖片,需要安裝一個庫pillow

pip install pillow

安裝後在python終端嘗試:

from PIL import Image, ImageDraw, ImageFont

# Image:畫布
# ImageDraw:畫筆
# ImageFont:字體(推薦使用一個字體庫FreeFont)

# 註意:訪問服務器的圖片,響應頭中的MIME類型必須為image/png或image/jpeg(之前都是text/html)

編寫返回圖片驗證碼的代碼

booktest/urls.py

urlpatterns = [
    url(^verifyCode$,views.verifyCode, name="verifyCode"),
] 

booktest/views.py

def verifyCode(request):
    from PIL import Image, ImageDraw, ImageFont
    import random
    # 規定寬高 寬和高的比例決定驗證碼的長度是多少 這裏是100/25=4
    width = 100
    height = 25
    # 背景色
    bgColor = (63,63,63) # 較深
    # 創建畫布
    # 參數1 mode 模式 RGB
    # 參數2 size 長度為2的元組  (width, height)
    # 參數3 color 畫布的背景色 長度為3的元組 (R,G,B)
    image = Image.new(RGB, (width, height), bgColor)
    # 創建畫筆
    # 參數1 im 畫布對象
    # 參數2 mode 模式 默認為None 
    draw = ImageDraw.Draw(image)
    # 創建字體
    # 參數1 font 字體文件
    # 參數2 字體大小
    font = ImageFont.truetype(FreeMono.ttf, 24)
    # 文字
    text = 0123456789
    textTemp = ‘‘
    # 逐個描繪字符
    for i in range(4):
        textTemp1 = text[random.randrange(0,len(text))]
        textTemp += textTemp1
        # 使用畫筆對象在畫布上描繪字符
        # 參數1 xy 要描繪的字符左上角的坐標 長度為2的元組
        # 參數2 text 要描述的字符 
        # 參數3 fill 要描述的字符的顏色
        # 參數4 font 字體
        draw.text((i*25,0), textTemp1, (255,255,255), font)

    print(textTemp)        
    # 把畫布保存到內存中
    #import cStringIO # python2的內存庫
    import io # python3中的內存庫
    buf = io.BytesIO()
    image.save(buf, png)
    # 將內存流中的內容輸出到客戶端
    return HttpResponse(buf.getvalue(), image/png)

接下來在網頁上顯示驗證碼

booktest/urls.py

urlpatterns = [
    url(^verifyCode$,views.verifyCode, name="verifyCode"),
    url(^verifyTest$,views.verifyTest, name="verifyTest"),
]

booktest/views.py

def verifyTest(request):
    context = {}
    return render(request, booktest/verifyTest.html, context)

templates/booktest/verifyTest.html

<body>
    <form method="post" action="/booktest/verifyTest2">
        {% csrf_token %}
        姓名:<input type="text" name="uname"/><br/>
        驗證碼:<input type="text" name="verifycode"/><img src="/booktest/verifyCode"><br/>
        <input type="submit" value="提交"/>
    </form>
</body>

verifyCode中,把隨機產生的驗證碼保存到session

booktest/views.py

def verifyCode(request):
    from PIL import Image, ImageDraw, ImageFont
    ... ...
    print(textTemp)

    # 保存到session中
    request.session[code] = textTemp
    
    # 把畫布保存到內存中
    ... ...
    

添加路由

booktest/urls.py

urlpatterns = [
    url(^verifyTest2$,views.verifyTest2, name="verifyTest2"),
]  

booktest/views.py

def verifyTest2(request):
    ori_code = request.session[code]
    post_code = request.POST[verifycode]
    print(ori_code:%s, post_code:%s % (ori_code, post_code))
    if ori_code == post_code:
        return HttpResponse(ok)
    else:
        return HttpResponse(fail)

訪問 http://127.0.0.1:8080/booktest/verifyTest 提交正確/錯誤驗證碼,後臺可以自行檢查了。

Django:模板template(二)