10.註冊和登入功能實現(3)—— 註冊資料寫入資料庫

Harpsichord1207發表於2019-02-16

現在資料獲取到了,提示也有了,我們需要把註冊的資料寫入到資料庫,這一步很簡單,直接使用之前提到過的方法,但是我們不能直接把明文密碼寫入到資料庫中,那樣做是十分不安全的,我們需要將其加密之後再寫進去,具體是用到werkzeug.security中的generate_password_hash這個函式,將字串變成hash值。
我們可以在User模型中重寫__init__函式(或__setattr__),當傳入password自動呼叫generate_password_hash進行加密,如:

class Users(db.Model):
    __tablename__ = `users_info`
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(32), nullable=False)
    password = db.Column(db.String(100), nullable=False)
    register_time = db.Column(db.DateTime, nullable=False, default=datetime.now())
    avatar_path = db.Column(db.String(256), nullable=False, default=`images/doraemon.jpg`)
    
    def __init__(self, *args, **kwargs):
        self.username = kwargs.get(`username`)
        self.password = generate_password_hash(kwargs.get(`password`))

這樣每新增一個新使用者,在init的時候就自動把密碼轉為hash值了,但是後續我們還得增加修改密碼的功能,所以就直接簡單點,在收到POST資料的時候就把密碼加密,然後存入資料庫中,此時註冊的檢視函式程式碼如下:

from flask import Flask, render_template, request, flash, redirect, url_for
from models import db, Users
from werkzeug.security import generate_password_hash
from exts import validate
import config

...

@app.route(`/register/`, methods=[`GET`, `POST`])
def register():
    if request.method == `GET`:
        return render_template(`register.html`)
    else:
        username = request.form.get(`username`)
        password1 = request.form.get(`password1`)
        password2 = request.form.get(`password2`)
        message = validate(username, password1, password2)
        flash(message)
        if `成功` in message:
            new_user = Users(username=username, password=generate_password_hash(password1))
            db.session.add(new_user)
            db.session.commit()
            return redirect(url_for(`login`))
        else:
            return render_template(`register.html`)

這裡獲取登入或註冊成功的狀態,使用了上一篇文章結尾說的方法,簡化了程式碼量。

實際上更簡單的方法是,我們直接對傳入的{{ message }}進行判斷,如果帶有`成功`字串,就顯示藍色,否則就顯示紅色。上文主要是為了說明@app.context_processor這個裝飾器,以及sessiong物件的區別。

那麼同樣的,登入的驗證過程,就不能直接去拿資料庫加密過的雜湊和原始的密碼對比了,我們用werkzeug.securitycheck_password_hash方法,它能驗證雜湊值是否與原始的密碼是匹配的,然後修改validate函式如下:

from models import Users
from werkzeug.security import check_password_hash


def validate(username, password1, password2=None):
    user = Users.query.filter(Users.username == username).first()
    if password2:
        if user:
            return `使用者名稱已經存在`
        else:
            if len(username) < 4:
                return `使用者名稱長度至少4個字元`
            elif password1 != password2:
                return `兩次密碼不一致`
            elif len(password1) < 6:
                return `密碼長度至少6個字元`
            else:
                return `註冊成功,請登入`
    else:
        if user:
            if check_password_hash(user.password, password1):
                return `登入成功`
            else:
                return `密碼錯誤`
        else:
            return `使用者名稱不存在`

登入頁面的檢視函式如下:

@app.route(`/login/`, methods=[`GET`, `POST`])
def login():
    if request.method == `GET`:
        return render_template(`login.html`)
    else:
        username = request.form.get(`username`)
        password = request.form.get(`password`)
        message = validate(username, password)
        if `成功` in message:
            return redirect(url_for(`home`))
        else:
            flash(message)
            return render_template(`login.html`)

相關文章