前言
之前我们在数据库中存储的用户密码为明文密码,这是很危险的。看自己公司业务代码对应的数据库不会存储明文密码,存储的一般是哈希密码。这样如果数据库被盗,无法得到用户的明文密码,只有哈希值。
哈希密码
哈希的意思是,将明文密码转换为看起来像乱码的字节序列,就是一个字符串。
示例
$2b$12$rYBjJXF01vXl1i8zFbmr4eEc4IA5g/giwoC1x52Aqhz4nt.LRdjCS
安装 passlib
PassLib 是一个用于处理哈希密码的很棒的 Python 包。
它支持许多安全哈希算法以及配合算法使用的实用程序。
推荐的算法是 「Bcrypt」。
因此,安装附带 Bcrypt 的 PassLib:pip install passlib[bcrypt]
当然也可以分别按照:
pip install passlib
pip install bcrypt
哈希并校验密码
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def get_password_hash(password: str) -> str:
"""
获取 hash 后的密码
:param password:
:return:
"""
return pwd_context.hash(password)
def verify_password(plain_password: str, hashed_password: str) -> bool:
"""
验证密码
:param plain_password: 原密码
:param hashed_password: hash后的密码
:return:
"""
return pwd_context.verify(plain_password, hashed_password)
这里解释一下pwd_context:
pwd_context是一个密码上下文对象(CryptContext)的实例化。
密码上下文是用于处理密码相关操作的工具。使用CryptContext类创建了一个密码上下文对象,并传入了两个参数:
schemes=["bcrypt"]:这表示密码上下文对象将使用 bcrypt 哈希算法来加密和验证密码。bcrypt 是一种常用的密码哈希算法,它具有较高的安全性和计算复杂性,可以有效防止暴力破解等攻击。deprecated="auto":这意味着当检测到密码的哈希算法不再被推荐使用时,CryptContext会自动更新为更安全的算法。
通过创建密码上下文对象,您可以使用其提供的方法来进行密码的加密和验证。
函数get_password_hash:对密码进行哈希加密
函数verify_password:验证给定的密码是否与哈希过的密码匹配
验证
get_password_hash("123456") # $2b$12$vBZ.OM88hMqcYJtV2H2hZe4v3gPcLN8Hw0CpomNH29hEgZH/ag96O
verify_password("123456", "$2b$12$vBZ.OM88hMqcYJtV2H2hZe4v3gPcLN8Hw0CpomNH29hEgZH/ag96O") # True
修改注册接口
原核心注册逻辑:
def register_user(username: str, password: str):
try:
with SessionLocal() as session:
user = session.query(User).filter(User.username==username, User.deleted_at==None).first()
if user:
return None, "用户名已存在"
db_obj = User(
username=username,
password=password,
)
session.add(db_obj)
session.commit()
session.refresh(db_obj)
return db_obj, None
except Exception as e:
UserService.log.error(f"用户{username}注册失败: {str(e)}")
return None, str(e)
只需要修改User对象中的password值即可,调用get_password_hash对密码进行哈希加密
修改如下
db_obj = User(
username=username,
password=get_password_hash(password),
)
其他都不变,再次请求注册接口,注册成功后,查看数据库中密码值已经是哈希密码了。