系統環境:Ubuntu 18.04.1 LTS
python
Python使用的是虛擬環境:virutalenv
linux
Python的版本:Python 3.6.9
web
基本大多數web應用都有用戶身份驗證。算法
基本的身份驗證,要不是用戶名,要不是電子郵件地址。加上本身的密碼。完成身份驗證。shell
這裏就是作一個完整的用戶身份驗證系統數據庫
Werkzeug的security模塊實現了散列值的計算。有兩個函數,一個生成,另一個核對flask
以下:安全
generate_password_hash(password,method='pbkdf2:sha256',salt_length=8)
session
三個輸入參數:app
pbkdf2_sha256 + SALT鹽值加密,是很可靠的一種加密方式。
輸入的值是一個密碼,輸出的值返回密碼散列值的字符串。基本默認值就夠用了。
check_password_hash(hash, password)
這個參數從數據庫中取出密碼的hash值和輸入的密碼值進行校對。若是返回爲True說明輸入的密碼正確。
在app/models.py
加入Werkzeug密碼散列值
from werkzeug.security import generate_password_hash, check_password_hash class User(db.Model): #.. password_hash = db.Column(db.String(128)) @property def password(self): raise AttributeError('password is not a readable attribute') @password.setter def password(self, password): self.password_hash = generate_password_hash(password) def verify_password(self, password): return check_password_hash(self.password_hash, password)
在shell測試上述代碼:
(zsdpy1) zsd@zsd-virtual-machine:~/Zflask$ flask shell Python 3.6.9 (default, Nov 7 2019, 10:44:02) [GCC 8.3.0] on linux App: app [production] Instance: /home/zsd/Zflask/instance >>> u = User() >>> u.password = 'cat' >>> u.password_hash 'pbkdf2:sha256:150000$bCVGWsku$752d59b87a450aac1b2ea9297e6475f2300fcdea4b589f788aa753e1a820c12d' >>> u.verify_password('cat') True >>> u.verify_password('zsd') False >>> u2 = User() >>> u2.password = 'cat' >>> u2.password_hash 'pbkdf2:sha256:150000$oMmeJziP$92900571f3639e0dca770bbb94f83c64a22d3f510343446a32499c2f64783962'
能夠看到u和u2的密碼雖然都是cat,可是hash密碼值確實不同的。
這樣手動寫shell一步一步測試特別浪費時間,咱們能夠經過寫單元測試,完成測試工做。以下:
tests/test_user_model.py
密碼散列測試
import unittest from app import create_app, db from app.models import User class UserModelTestCase(unittest.TestCase): def setUp(self): self.app = create_app('testing') self.app_context = self.app.app_context() self.app_context.push() db.create_all() def tearDown(self): db.session.remove() db.drop_all() self.app_context.pop() def test_password_setter(self): u = User(password='cat') self.assertTrue(u.password_hash is not None) def test_no_password_getter(self): u = User(password='cat') with self.assertRaises(AttributeError): u.password def test_password_verification(self): u = User(password='cat') self.assertTrue(u.verify_password('cat')) self.assertFalse(u.verify_password('dog')) def test_password_salts_are_random(self): u = User(password='cat') u2 = User(password='cat') self.assertTrue(u.password_hash != u2.password_hash)
執行下列命令,作單元測試 :
(zsdpy1) $ flask test test_app_exists (test_basics.BasicsTestCase) ... ok test_app_is_testing (test_basics.BasicsTestCase) ... ok test_no_password_getter (test_user_model.UserModelTestCase) ... ok test_password_salts_are_random (test_user_model.UserModelTestCase) ... ok test_password_setter (test_user_model.UserModelTestCase) ... ok test_password_verification (test_user_model.UserModelTestCase) ... ok ---------------------------------------------------------------------- Ran 6 tests in 2.760s
這樣就至關於自動化測試,直接測試了剛剛shell作得測試工做。