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

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

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

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

目錄

一丶登入後端介面編寫

二丶登入介面測試

三丶登入前端編寫

四丶使用者登入功能測試

五丶定義檢查登入狀態與使用者退出介面 

六丶效果圖


 

一丶登入後端介面編寫

1.獲取引數

req_dict = request.get_json()
mobile = req_dict.get("mobile")
password = req_dict.get("password")

2.校驗引數的完整性

if not all([mobile, password]):
    return jsonify(errno=RET.PARAMERR, errmsg="請求引數不完整")

3.校驗手機號碼格式

if not re.match(r"1[345789]\d{9}", mobile):
    return jsonify(errno=RET.PARAMERR, errmsg="手機號碼格式錯誤")

4.將使用者登入的錯誤次數以使用者的IP作為標識,儲存到redis資料庫中,通過redis資料庫來限制時間,如次數超過10分鐘內錯誤登入超過5次

  • step1 獲取使用者IP地址
user_ip = request.remote_addr
  • step2 判斷使用者登入錯誤次數是否超出限制
try:
    access_nums = redis_store.get("access_nums_%s" % user_ip)
except Exception as e:
    current_app.logger.error(e)
else:
    if access_nums is not None and int(access_nums) >= constants.LOGIN_ERROR_MAX_TIMES:
        return jsonify(errno=RET.REQERR, errmsg="錯誤次數過多,請稍後重試")

5.從資料庫中根據使用者手機號查詢對應的資料物件user

try:
    user = User.query.filter_by(mobile=mobile).first()
except Exception as e:
    current_app.logger.error(e)
    return jsonify(errno=RET.DBERR, errmsg="獲取使用者資訊失敗")

6.校驗使用者輸入的手機號以及密碼與資料庫是否一致,將使用者名稱(手機號)與密碼放在一起進行校驗,不管是密碼錯誤還是使用者名稱錯誤,返回的提示資訊都為使用者名稱或密碼錯誤,不展示細節與前端上

  • step1 在models中定義一個校驗密碼的函式
def check_password(self, passwd):
    """
    檢驗使用者輸入密碼與資料庫中密碼是否一致
    :param passwd: 使用者輸入的原始密碼
    :return: 匹配正確返回True 否則 返回false
    """
    return check_password_hash(self.password_hash, passwd)
  • step2 回過頭在passport中進行校驗
if user is None or user.check_password(password) is False:
    return jsonify(errno=RET.DATAERR, errmsg="使用者名稱或密碼錯誤")

7.驗證失敗需要記錄失敗次數,儲存到redis資料庫中

  • step1 通過redis資料庫python中的incr方法累積儲存access_nums_ip到redis資料庫中
redis_store.incr("access_nums_%s" % user_ip)
  • step2 設定access_nums_ip鍵的有效期
redis_store.expire("access_nums_%s" % user_ip, constants.LOGIN_ERROR_FORBID_TIME)
  • step3 丟擲異常,並記錄到日誌中
try:
    redis_store.incr("access_nums_%s" % user_ip)
    redis_store.expire("access_nums_%s" % user_ip, constants.LOGIN_ERROR_FORBID_TIME)
except Exception as e:
    current_app.logger.error(e)

8.如果使用者名稱和密碼驗證成功,則將登入成功狀態儲存到session中,並返回正確響應

session["name"] = user.name
session["mobile"] = user.mobile
session["id"] = user.id

return jsonify(errno=RET.OK, errmsg="登入成功")

二丶登入介面測試

1.在ihome/init中註釋CSRF驗證,執行程式

python manage.py runserver

2.Postman測試工具中新增127.0.0.1:5000/api/v1.0/sessions登入介面路由

3.檢視之前我們測試註冊介面時註冊的賬號密碼

 4.在Postman工具中構造Body體JSON資料

  • step1 構造錯誤資料,輸入錯誤密碼,檢視提示

  • step2 輸入錯誤賬號

  • step3 多次錯誤登入

檢視資料庫中儲存的登入錯誤次數

  • step4 輸入正確賬號和密碼

三丶登入前端編寫

1.前端登入HTML程式碼(不展示)

2.前端登入JS程式碼(不展示)

3.在login.js中在submit提交回調函式中進行如下編寫

// 將表單的資料存到物件data中
var data = {
    mobile:mobile,
    password:passwd
};
// 將data資料轉換成json字串
var jsonData = JSON.stringify(data);
$.ajax({
    url:"/api/v1.0/sessions",
    type:"post",
    data:jsonData,
    contentType:"application/json",
    dataType:"json",
    headers:{
        "X-CSRFToken":getCookie("csrf_token")
    },
    success:function (data) {
        if(data.errno == "0"){
            // 則代表登入成功,跳轉到主頁
            location.href = "/";
        }
        else {
            // 登入不成功則在頁面中顯示錯誤資訊
            $("#password-err span").html(data.errmsg);
            $("#password-err").show();
        }
    }
})

4.在js構建一個getCookie的方法來獲取前端名為csrf_token的cookie的值

function getCookie(name) {
    var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
    return r ? r[1] : undefined;
}

5.將獲取的cookie的值,放在請求頭中的X-CSRFToken鍵中,方便後端進行csrf驗證(需將ihome/init中的CSRF驗證開啟)

headers:{
          "X-CSRFToken":getCookie("csrf_token")
        },

四丶使用者登入功能測試

1.執行程式後,在http://127.0.0.1:5000/login.html 上進行測試

2.輸入錯誤的賬號或密碼

3.輸入正確的使用者名稱和密碼,跳轉到主頁(這裡還沒有完善,在登入成功後右上角不再顯示登入與註冊,而是顯示登入時的使用者名稱 )

五丶定義檢查登入狀態與使用者退出介面 

1.檢查登入狀態

@api.route("/session", methods=["GET"])
def check_login():
    """
    檢查登入狀態
    :return:
    """
    # 從註冊和登入成功時儲存到session資料中獲取name的值
    name = session.get("name")
    # name不為空,則返回ok,並將name以字典形式傳給前端,為空則返回對應錯誤資訊
    if name is not None:
        return jsonify(errno=RET.OK, errmsg="true", data={"name":name})
    else:
        return jsonify(errno=RET.SESSIONERR, errmsg="false")

2.使用者退出(清除session資料)

@api.route("/session", methods=["DELETE"])
def logout():
    """
    使用者退出 清除session資料
    :return:
    """
    session.clear()
    return jsonify(errno=RET.OK, errmsg="OK")

3.登入成功時,跳轉到主頁,那麼在index.js中進行編寫,因為是當頁面載入完時需要顯示出使用者名稱,所以在$(document).ready下進行編寫即可

$.get("/api/v1.0/session", function (resp) {
        if (resp.errno == "0"){
            $(".top-bar>.user-info>.user-name").html(resp.data.name);
            $(".top-bar>.user-info").show();
        }
        else {
            $(".top-bar>.register-login").show();
        }
    }"json");

4.當登入成功後,主頁右上角顯示使用者名稱(手機號),點選使用者名稱進入後,在個人主頁,點選退出再回到主頁,此時主頁右上角顯示登入和註冊,那麼需要在my.js中進行如下程式碼編寫

function logout() {
    $.ajax({
        url:"/api/v1.0/session",
        type:"delete",
        headers:{
            "X-CSRFToken":getCookie("csrf_token")
        },
        dataType:"json",
        success:function (resp) {
            if (resp.errno == "0"){
                location.href = "/"
            }
        }
    })
}

六丶效果圖