1. 程式人生 > >Flask Web 開發 使用者認證

Flask Web 開發 使用者認證

進入第二部分了,估計會很難,第一部分還有好多點的原理沒搞清楚,不過先做起來吧。

使用者認證其實說簡單點就是使用者名稱和密碼是否匹配的過程。下面這段書裡面的文件,應該說說的比較詳細,就直接複製了

設計Web 程式時,人們往往會高估資料庫中使用者資訊的安全性。如果攻擊者入侵伺服器獲取了資料庫,使用者的安全就處在風險之中,這個風險比你想象的要大。眾所周知,大多數
使用者都在不同的網站中使用相同的密碼,因此,即便不儲存任何敏感資訊,攻擊者獲得儲存在資料庫中的密碼之後,也能訪問使用者在其他網站中的賬戶。
若想保證資料庫中使用者密碼的安全,關鍵在於不能儲存密碼本身,而要儲存密碼的雜湊值。計算密碼雜湊值的函式接收密碼作為輸入,使用一種或多種加密演算法轉換密碼,最終
得到一個和原始密碼沒有關係的字元序列。核對密碼時,密碼雜湊值可代替原始密碼,因為計算雜湊值的函式是可復現的:只要輸入一樣,結果就一樣。

使用者認證這一塊功能,我們要開始用到werkzeug工具包了,裡面用於認證密碼的部分,我們需要用到security模組中的2個功能

generate_password_hash(password, method=pbkdf2:sha1, salt_length=8):這個函式將
原始密碼作為輸入,以字串形式輸出密碼的雜湊值,輸出的值可儲存在使用者資料庫中。
method 和salt_length 的預設值就能滿足大多數需求。
check_password_hash(hash, password):這個函式的引數是從資料庫中取回的密碼雜湊
值和使用者輸入的密碼。返回值為True 表明密碼正確。

而密碼認證這一塊,我們應該放在models裡面進行設定

首先from werkzeug.security import generate_password_hash, check_password_hash

隨後,在User的類裡面,進行屬性新增


計算密碼雜湊值的函式通過名為password 的只寫屬性實現。設定這個屬性的值時,賦值方法會呼叫Werkzeug 提供的generate_password_hash() 函式,並把得到的結果賦值給password_hash 欄位。如果試圖讀取password 屬性的值,則會返回錯誤,原因很明顯,因為生成雜湊值後就無法還原成原來的密碼了。
verify_password 方法接受一個引數( 即密碼), 將其傳給Werkzeug 提供的check_password_hash() 函式,和儲存在User 模型中的密碼雜湊值進行比對。如果這個方法返回
True,就表明密碼是正確的。

隨後我們進行密碼的設定和測試


我們可以看到,你就算建立了u和u2的密碼是相同的,他雜湊化以後出來的值也是不一樣的

而且你如果在設定密碼後嘗試去訪問u2的password屬性,他會報錯,因為密碼已經被雜湊化了。

另外說個題外話:

在模型被修改後,資料庫裡的資料模型其實並沒有被修改,所以我覺得應該是後期需要用到資料庫遷移了才會更新資料庫


接著課本上要求註冊不同的藍本了,這裡插一句我對於blueprint的理解

看了網上很多的講解,都說藍本是將功能模組化,也就是將功能區分開

我實際上不是很理解,不過後來我看到每個註冊的藍圖包下面,都會有一個views,就覺得,blueprint的作用其實是將每個功能分開,核心是將views模組打散

這樣,views就不用一股腦寫在一個檔案裡面了,不然到後期維護,一個views幾千條,就得累死。

首先我們講

為auth模組註冊藍圖

app/auth/__init__.py:建立藍本
from flask import Blueprint
auth = Blueprint('auth', __name__)
from . import views

app/auth/views.py:藍本中的路由和檢視函式
from flask import render_template
from . import auth
@auth.route('/login')
def login():
return render_template('auth/login.html')               #由於是註冊了auth模組,所以,他讀取的是auth資料夾裡面的模板,而這個模板資料夾,必須在app/templates下面建立

#因為Flask 認為模板的路徑是相對於程式模板資料夾而言的。

auth 藍本要在create_app() 工廠函式中附加到程式上,如示例8-5 所示。
app/__init__.py:附加藍本


def create_app(config_name):
# ...
from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint, url_prefix='/auth')     #註冊藍本時使用的url_prefix 是可選引數。如果使用了這個引數,註冊後藍本中定義的
return app                                                                                       #所有路由都會加上指定的字首,即這個例子中的/auth。例如,/login 路由會註冊成/auth/
                                                                                                          #login,在開發Web 伺服器中,完整的URL 就變成了http://localhost:5000/auth/login

這裡關於url_prefix這個字首有個

首先第一點:重複一下,如果設定了url_prefix這個引數,那麼在templates下面,必須要有對應的blueprint名字的資料夾,藍圖的檢視函式讀取的是那個裡面的模板

比如,auth藍圖,他讀取的是app/templates/auth/xxxxx.html

當然,你也可以讀取templates根目錄下面的html檔案,那就需要你就要把註冊藍圖時候的url_prefix去掉,並在路由裡面返回的時候,把前置路徑去掉即可,如果他讀取不到你所範圍的html,那麼他就會報404,這個例子中,我們用test.html來做測試。



我們將main藍圖不設定url_prefix,則他讀取的應該是templates根目錄下的test.html



當然,如果我們強行修改路由引數的範圍值,他也可以指定到資料夾內部去


我對這部分知識的理解是:通過在藍圖註冊時候的引數url_prefix,你可以選擇是否有字首

而具體返回哪個路徑的模板檔案,你還是要在views裡面修改,但貌似不是預設強制讀取藍圖資料夾的,而是作為一種規範