查看sys_user表(如下图),可以发现密码是明文,安全性不高,所以需要进行加密。

封装数据库CURD
新建 core/crud.py 文件:
python
from typing import Any, Generic, NewType, TypeVar
from tortoise.models import Model
from pydantic import BaseModel
from tortoise.expressions import Q
ModelType = TypeVar("ModelType", bound=Model)
CreateSchemaType = TypeVar("CreateSchemaType", bound=BaseModel)
UpdateSchemaType = TypeVar("UpdateSchemaType", bound=BaseModel)
Total = NewType("Total", int)
class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
def __init__(self, model: type[ModelType]):
self.model = model
async def get(self, id: int) -> ModelType:
"""根据ID获取单个记录"""
return await self.model.get(id=id)
async def list(self, page: int, page_size: int, search: Q = Q(), order: list | None = None) -> tuple[Total, list[ModelType]]:
"""分页查询记录列表"""
query = self.model.filter(search)
if order is None:
order = []
total = await query.count()
items = await query.offset((page - 1) * page_size).limit(page_size).order_by(*order)
return total, items
async def create(self, obj_in: CreateSchemaType) -> ModelType:
"""创建新记录"""
if isinstance(obj_in, dict):
obj_dict = obj_in
else:
obj_dict = obj_in.model_dump()
obj = self.model(**obj_dict)
await obj.save()
return obj
async def update(self, id: int, obj_in: UpdateSchemaType | dict[str, Any]) -> ModelType:
"""更新指定记录"""
if isinstance(obj_in, dict):
obj_dict = obj_in
else:
obj_dict = obj_in.model_dump(exclude_unset=True, exclude={"id"})
obj = await self.get(id=id)
obj = obj.update_from_dict(obj_dict)
await obj.save()
return obj
async def remove(self, id: int) -> None:
"""删除单个记录"""
obj = await self.get(id=id)
await obj.delete()
async def bulk_remove(self, ids: str) -> None:
"""批量删除记录"""
id_list = ids.split(",")
await self.model.filter(id__in=id_list).delete()
封装密码加密
安装依赖
首先安装 passlib 库:
shell
pip install passlib[bcrypt] setuptools argon2-cffi
实现密码工具
新建 utils/crud.py 文件:
python
from passlib import pwd
from passlib.context import CryptContext
# 使用 Argon2 算法创建密码上下文
pwd_context = CryptContext(schemes=["argon2"], deprecated="auto")
def verify_password(plain_password: str, hashed_password: str) -> bool:
"""验证明文密码与哈希密码是否匹配"""
return pwd_context.verify(plain_password, hashed_password)
def get_password_hash(password: str) -> str:
"""生成密码哈希值"""
return pwd_context.hash(password)
def generate_password() -> str:
"""生成随机密码"""
return pwd.genword()
创建UserRepository
安装依赖
shell
pip install pydantic[email]
创建Schemas
新建 schemas/users.py 文件:
python
from datetime import datetime
from pydantic import BaseModel, EmailStr, Field
class BaseUser(BaseModel):
id: int
account: str | None = None
username: str | None = None
email: EmailStr | None = None
is_active: bool | None = True
is_superuser: bool | None = False
created_at: datetime | None
updated_at: datetime | None
last_login: datetime | None
roles: list | None = []
class UserCreate(BaseModel):
account: str = Field(example="admin")
username: str = Field('', example="Admin1")
gender: int | None = Field(0, description="性别")
password: str = Field(
default="admin1234",
example="AdminPass123",
min_length=8,
description="密码(至少8位,包含字母和数字)",
)
avatar: str | None = Field('', description="用户头像")
mobile: str = Field(None, description="联系方式")
email: EmailStr = Field('', example="admin@qq.com")
status: int | None = Field(1, description="状态")
is_active: bool | None = True
is_superuser: bool | None = False
dept_id: int | None = Field(0, description="部门ID")
create_by: int | None = Field(None, description="创建人")
update_by: int | None = Field(None, description="修改人")
class UserUpdate(BaseModel):
id: int
account: str
username: str = Field('', example="Admin1")
gender: int | None = Field(0, description="性别")
avatar: str | None = Field('', description="用户头像")
mobile: str | None = Field('', description="联系方式")
email: str | None = Field('', example="admin@qq.com")
status: int | None = Field(1, description="状态")
is_active: bool | None = True
is_superuser: bool | None = False
role_ids: list[int] | None = []
dept_id: int | None = 0
update_by: int | None = Field(None, description="修改人")
创建Repository
新建 repositories/user.py 文件:
python
from core.crud import CRUDBase
from models.admin import User
from schemas.users import UserCreate, UserUpdate
from utils.password import get_password_hash
class UserRepository(CRUDBase[User, UserCreate, UserUpdate]):
def __init__(self):
super().__init__(model=User)
async def create_user(self, obj_in: UserCreate) -> User:
obj_in.password = get_password_hash(password=obj_in.password)
obj = await self.create(obj_in)
return obj
user_repository = UserRepository()
修改初始化文件
修改core/insert_data.py文件:
python
from repositories.user import UserCreate, user_repository
...
async def init_superuser():
logger.info("🔧 开始初始化超级管理员用户...")
user = await user_repository.model.exists()
if not user:
await user_repository.create_user(
UserCreate(
account="admin",
username="超级管理员",
email="admin@admin.com",
password="abcd1234",
dept_id=1,
is_active=True,
is_superuser=True,
)
)
logger.info("✅ 超级管理员用户创建成功 - 用户名: admin")
else:
logger.info("ℹ️ 超级管理员用户已存在,跳过创建")
先清空sys_user表,之后再运行项目,运行成功之后可以看到密码已经加密了。
