作者:@张扶摇
本文为作者原创,转载请注明出处:https://www.cnblogs.com/zhangshengdong/p/12561678.html
目录
【简说Python WEB】用户身份验证--Werkzeug
Flask的security扩展
使用Werkzeug生成密码散列值
系统环境:Ubuntu 18.04.1 LTS
Python使用的是虚拟环境:virutalenv
Python的版本:Python 3.6.9
【简说Python WEB】用户身份验证--Werkzeug
基本大多数web应用都有用户身份验证。
基本的身份验证,要不是用户名,要不是电子邮件地址。加上自己的密码。完成身份验证。
这里就是做一个完整的用户身份验证系统
Flask的security扩展
- FLask-Login:管理已经登录的用户会话
- Werkzeug:计算密码散列值,同时进行check
- itsdangerous:生成并check加密安全令牌
使用Werkzeug生成密码散列值
Werkzeug的security模块实现了散列值的计算。有两个函数,一个生成,另外一个核对
如下:
generate_password_hash(password,method='pbkdf2:sha256',salt_length=8)
三个输入参数:
- 第一个参数: 输入密码
- 第二个参数:pbkdf2_sha256加密验证算法
- 第三个参数:salt值字符串长度。
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做得测试工作。
感谢您的阅读,如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮。本文欢迎各位转载,但是转载文章之后必须在文章页面中给出作者和原文连接。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统