【Python项目实战】用户系统:注册登录与密码哈希
2026/9/14 22:18:37 网站建设 项目流程

现在你的博客有个大漏洞:任何人都能发文章、删文章。

今天装上门禁——注册、登录、登出,顺便回答【Python项目实战】项目·强密码生成器:随机、安全与剪贴板这篇文章里埋的那个问题:为什么密码必须“哈希加盐”存储

🎯本篇成品:博客v3——注册、登录、登出、flash提示、登录门禁(没登录不能写/删)。

零新增依赖:密码哈希用的werkzeug随Flask自带。含注释约130行。


📌 太长不看版(给想快速上手的你)

项目信息一句话说明
项目名称Flask博客(v3·用户系统版)
代码行数~130行(含注释) + 模板文件
依赖零新增werkzeug随Flask自带
核心功能注册 + 登录 + 登出 + 登录门禁 + flash提示
跑起来的命令python main.py→ 浏览器打开http://127.0.0.1:5000
核心知识点密码哈希加盐、session会话、自定义装饰器
做完你能得到一个有门禁的博客,从“玩具”变“产品”!

一、密码为什么不能明文存(第9篇伏笔兑现)

假设数据库泄露了(忘改debug、弱密码后台、云盘误分享……),两种结局:

存储方式攻击者看到的后果
明文存密码打开表,所有账号当场沦陷大多数人到处复用密码,沦陷会蔓延到邮箱、支付账号
哈希存一串$scrypt$32768$8$1$...的天书没有密码原文,登录不了

🔪 哈希函数是单向的碎纸机

📌把密码绞成指纹容易,从指纹还原密码(目前)不可能。

登录时做的不是“解密密码”,而是把你输入的密码重新绞一遍,比对两坨指纹是否一致。


🧂 “加盐”是什么?

问题加盐的解法
如果两个用户密码相同,哈希值也相同盐 = 给每个密码撒一把随机字符再哈希
攻击者提前算好“常见密码→哈希”对照表(彩虹表),按表查就破解了让相同的密码生出不同的哈希,彩虹表直接作废

🧪 亲手验证

💡secrets是“必须不可预测”,werkzeug的盐是“故意每次不同”——方向相反的一对

>>>fromwerkzeug.securityimportgenerate_password_hash>>>generate_password_hash("python666")'scrypt:32768:8:1$saltA$...'>>>generate_password_hash("python666")'scrypt:32768:8:1$saltB$...'# 同一个密码,两个完全不同的哈希

好消息:这两个函数在werkzeug.security里,Flask自带werkzeug——本篇零新增依赖。


二、第二个概念:session——HTTP的“记忆手环”

HTTP是无状态的:每个请求都是陌生人,上一秒登录、下一秒服务器就把你忘了。

session就是解决方案:登录成功后服务器发你一个“签名手环”(Cookie),之后每个请求亮手环,Flask验签后知道“你是谁”。

概念比喻说明
session["uid"] = 用户id手环内容由Flask用SECRET_KEY签名,篡改内容签名就对不上,手环自动作废
SECRET_KEY手环的防伪印刷术泄露它,任何人都能伪造登录

三、第0步:setup

1. 复制flask_blog_v2为flask_blog_v3(保留v2) 2. 激活venv 3. 无需安装任何新包(werkzeug随Flask自带) 4. git commit一次干净的起点

四、第1步:SECRET_KEY——手环的防伪印刷术

importos app=Flask(__name__)app.config["SQLALCHEMY_DATABASE_URI"]="sqlite:///blog.db"app.config["SQLALCHEMY_TRACK_MODIFICATIONS"]=False# 生产环境:从环境变量读(第5篇军规——密钥不进仓库)app.config["SECRET_KEY"]=os.environ.get("BLOG_SECRET_KEY","dev-only-do-not-use-in-prod")

⚠️ 两个注意点

#注意点说明
没有SECRET_KEY就用sessionFlask会当场报错(第十节①)
SECRET_KEY必须固定每次启动随机生成的话,重启一次全体用户被“踢下线”(第十节③)

五、第2步:User模型——存指纹,不存密码

fromwerkzeug.securityimportgenerate_password_hash,check_password_hashclassUser(db.Model):__tablename__="users"id=db.Column(db.Integer,primary_key=True)username=db.Column(db.String(40),unique=True,nullable=False)password_hash=db.Column

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询