1. 程式人生 > >Flask專案之手機端租房網站的實戰開發(四)

Flask專案之手機端租房網站的實戰開發(四)

說明:該篇部落格是博主一字一碼編寫的,實屬不易,請尊重原創,謝謝大家!

接著上一篇部落格繼續往下寫 :https://blog.csdn.net/qq_41782425/article/details/85676643

注:在此專案中我不會使用程式碼塊插入程式碼,而是通過插入圖片來進行演示,防止CV大法,你懂得~

目錄

一丶在專案中新增靜態資原始檔

二丶關於csrf防護機制

三丶使用者註冊模組(圖片驗證碼以及簡訊驗證碼)

四丶測試後端verify_code介面是否正確


一丶在專案中新增靜態資原始檔

1.將靜態資原始檔拷貝到專案static目錄下

2.在終端上執行專案python manage.py runserver

3.在瀏覽器中輸入http://127.0.0.1:5000/static/html/index.html 訪問前端主頁,如下圖

4.當在不使用nginx伺服器給使用者提供靜態資源,而是以flask來提供,當用戶在瀏覽器中輸入/static/html/index.html就會顯得不友好,正常來說訪問主頁只需要輸入ip地址或者是域名加埠號就可以了,那麼就需要我們專門寫個檢視函式來提供有好的連結地址,把地址字首給去掉

5.建立一個藍圖,專門負責提供靜態檔案的

  • step1 在ihome目錄下建立一個web_html.py檔案
  • step2 建立藍圖html
html = Blueprint("web_html", __name__)
  • step3 在utils目錄下建立一個__init__.py檔案,使這個目錄變成python的包,然後在這個utils包中建立commons.py檔案,作為通用工具,在裡面定義一個正則轉換器

  • step4 在ihome/init檔案中,在建立app物件時候,將ReConverter物件新增到app中

  • step5 回到commons.py檔案中,定義檢視函式get_html

  • step6 在ihome/init中進入此藍圖註冊

  • step7 啟動專案
python manage.py runserver
  • step8
    清除網頁快取資料

 二丶關於csrf防護機制

1.csrf驗證機制:從cookie中獲取一個csrf_token的值,再從請求體中獲取一個csrf_token的值,如果這兩個值相同,則檢
驗通過,可以進入檢視函式中執行,如果兩個值不同,則檢驗失敗,會想前端返回狀態碼404的錯,之前在ihome/init中設定的csrf只是負責驗證,並不負責cookie與請求體中的csrf_token的值從哪裡來

    # 為flask補充csrf防護
    CSRFProtect(app)

2.分析:前後端不分離時跟django一樣直接在模板中進行設定csrf,而我們這個專案使用的是前後端分離,沒有模板,對於cookie我們可以提前進行設定csrf_token,然後對於請求體中的cookie而言,當 傳送POST請求時,就將那時候的請求體資料中設定csrf_token這樣就能csrf防護了

3.設定cookie中的csrf_token

  • step1 為web_html.py中匯入csrf包
from flask_wtf import csrf
  • step2 建立一個csrf_token的值 
csrf_token = csrf.generate_csrf()
  • step3 匯入make_response,將返回的靜態檔案方法的值構建成響應物件
resp = make_response(current_app.send_static_file(html_file_name))
  • step4 設定cookie的值,有效期為臨時會話
resp.set_cookie("csrf_token", csrf_token)
  •  step5 重新啟動程式,重新整理網頁,檢視我們設定的cookie

三丶使用者註冊模組(圖片驗證碼以及簡訊驗證碼)

 1.圖片驗證碼使用流程

  • step1 分析流程:

第一步,需要前端像後端發起一個獲取圖片驗證碼的請求,對於後端來說就需要去生成一個隨機的驗證碼圖片;第二步將生成的驗證碼圖片返回給前端;第三步驗證圖片驗證碼的準確性,如果正確,才能發起獲取簡訊驗證碼的請求

  • step2 具體細節

在發起獲取簡訊驗證碼請求的時候將攜帶填寫的圖片驗證碼與後端生成的圖片驗證碼進行校驗,因此後端在生成圖片驗證碼的時候,需要將圖片進行儲存,意義是為了與使用者輸入的圖片驗證碼進行對比,對比成功,才會給使用者返回簡訊驗證碼

  • step3 問題分析

後端生成的圖片驗證碼是存在哪裡,誰來維護有效期,不可能一張圖片一直用下去,所以將在後端生成的圖片驗證碼,存到redis資料庫中,在後端進行驗證的時候,就從redis中取出這個值,與前端使用者輸入的值進行對比即可;但是對於多個使用者來說同一時間向我傳送獲取圖片驗證碼時,該怎麼去判斷誰是誰的,所以要將圖片驗證碼進行編號處理,來分辨是屬於哪個使用者的圖片驗證碼,那麼就需要在使用者發起簡訊驗證碼請求的攜帶引數裡面除了填寫的圖片驗證碼,還需要攜帶一個使用者編號,因此對於後端伺服器來說,除了生成圖片驗證碼的值,還需要生成一個對應驗證碼的編碼,一起儲存到redis資料庫中,還需要將驗證碼值和編碼返回給前端使用者,那麼就需要從返回的響應體中取解析編碼,這樣做太麻煩了,為了減輕後端的壓力,將不再由後端去生成這個編碼了,而是由前端在一開始就去生成這個編號,再前端向後端伺服器發起獲取圖片驗證碼請求的時候攜帶一個編碼引數,然後後端將編碼和圖片驗證碼的值一起存到redis資料庫中

  • step4 在ihome/api_1_0目錄下建立一個verify_code.py檔案,將圖片驗證碼以及簡訊驗證碼放在這個檔案裡面進行使用
  • step5 使用restful風格構建前端向後端發起圖片驗證碼請求地址
GET http://127.0.0.1:5000/api/v1.0/image_codes/<image_code_id>

2.圖片驗證碼後端介面編寫

  • step1 將圖片驗證碼工具包captcha拷貝到ihome/utils目錄下
  • step2 在verify.py中匯入captcha包中的captcha模組中的captcha物件
from ihome.utils.captcha.captcha import captcha
  • step3 通過呼叫captcha物件中的generate_captcha方法來獲取生成的驗證碼名字,文字內容,以及圖片二進位制資料
name, text, image_data = captcha.generate_captcha()
  • step4 選擇儲存資料型別,將驗證碼的文字內容以及編碼存到redis資料庫中,並設定有效期

可以使用雜湊格式進行儲存,但是無法設定單個圖片的有效期

示例:

"image_codes": {"id1":"abc", "":""} 雜湊  hset("image_codes", "id1", "abc")  hget("image_codes", "id1")

使用字串格式對資料進行儲存,以編碼作為key,以文字內容作為value值進行儲存即可

示例:

"image_code_編號1": "真實值"
"image_code_編號2": "真實值"
redis_store.set("image_code_%s" % image_code_id, text)
redis_store.expire("image_code_%s" % image_code_id, constants.IMAGE_CODE_REDIS_EXPIRES)
  • step5 在verify.py中匯入redis資料庫連線物件,然後將編碼和文字內容存到redis資料庫
from ihome import redis_store

redis_store.set("image_code_%s" %image_code_id, text)
  • step6 設定圖片驗證碼有效期為三分鐘,首先在ihome目錄下建立一個constants.py檔案,用於存放常量
redis_store.expire("image_code_%s" %image_code_id, constants.IMAGE_CODE_REDIS_EXPIRES)

 設定值和有效期一步到位

redis_store.setex("image_code_%s" %image_code_id, constants.IMAGE_CODE_REDIS_EXPIRES, text)
  • step7 對於資料庫連線,可能會出現連線錯誤以及連線不上等問題,所以需要捕獲異常,並且將捕獲到的異常儲存到日誌中
current_app.logger.error(e)
  • step8 當出現異常後,需要返回錯誤資訊的json資料,先將工程專案定義好的response_code.py響應狀態碼檔案,拷貝到utils中

return jsonify(errno=RET.DBERR, errmsg="save image code failed")
  • step9 沒有出現異常,則先通過make_response構造圖片image_data資料響應體物件,再設定該響應體物件的請求頭中的Content-Type為圖片格式jpg,返回給前端

 

 3.開發流程與編寫介面文件

  • step1 開發流程

1. 分析需求
           2. 編寫程式碼
           3. 編寫單元測試
           4. 自測
           5. 編寫介面文件
           6. 提測程式碼

  • step2 編寫介面文件
介面文件

1. 介面名字
2. 描述(描述清楚介面的功能)
3. url
4. 請求方式
5. 傳入引數
6. 返回值


介面:獲取圖片驗證碼

描述:前端訪問,可以獲取到驗證碼圖片

url: /api/v1.0/image_codes/<image_code_id>

請求方式: GET

傳入引數:
    格式:路徑引數 (引數是查詢字串、請求體的表單、json、xml)

    名字             型別       是否必須      說明
   image_code_id    字串       是         驗證碼圖片的編號

返回值:
    格式: 正常:圖片, 異常:json

    名字             型別       是否必傳      說明
    errno          字串         否        錯誤程式碼
    errmsg         字串         否        錯誤內容

    例項:
    '{"errno": "4001", "errmsg": "儲存圖片驗證碼失敗"}'

四丶測試後端verify_code介面是否正確

1.需要在api_1_0/init中匯入我們寫的介面檔案verify_code讓藍圖知道有一個verify_code的模組

from . import verify_code

2.執行程式

python manage.py runserver

3.在瀏覽器中輸入http://127.0.0.1:5000/api/v1.0/image_codes/123,成功顯示出驗證碼圖片

4.檢視程式執行日誌

5.此時檢視redis資料庫中,會發現出現了一個image_code_123的鍵,獲取該鍵的值就是圖片驗證碼的文字值,說明我們寫的後端介面沒問題