基于ThinkPHP6用户登录逻辑,结合FastAPI框架实现用户登录系统的全流程解析,涵盖路由配置、数据验证、JWT令牌生成与鉴权、中间件依赖等核心环节:
路由定义:使用APIRouter
组织用户认证相关接口(注册、登录),并通过app.include_router()
集成到主应用。例如:
# routers/auth.py
from fastapi import APIRouter
router = APIRouter(prefix="/auth", tags=["Authentication"])
@router.post("/register")
async def register(user: UserRegisterSchema):
...
@router.post("/login")
async def login(user: UserLoginSchema):
...
引用:2977
请求数据模型:通过Pydantic模型定义请求参数,实现数据校验与自动文档生成:
from pydantic import BaseModel
class UserLoginSchema(BaseModel):
username: str
password: str
引用:62
密码哈希存储:使用passlib
的bcrypt
算法加密密码,避免明文存储:
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def hash_password(password: str) -> str:
return pwd_context.hash(password)
引用:185
用户唯一性校验:注册时检查用户名是否已存在:
async def register(user: UserRegisterSchema, db: Session = Depends(get_db)):
existing_user = db.query(User).filter(User.username == user.username).first()
if existing_user:
raise HTTPException(status_code=400, detail="用户已存在")
hashed_pwd = hash_password(user.password)
db_user = User(username=user.username, password=hashed_pwd)
db.add(db_user)
db.commit()
引用:1
身份验证:查询数据库并验证密码哈希:
def verify_password(plain_pwd: str, hashed_pwd: str) -> bool:
return pwd_context.verify(plain_pwd, hashed_pwd)
async def authenticate_user(username: str, password: str, db: Session):
user = db.query(User).filter(User.username == username).first()
if not user or not verify_password(password, user.password):
return None
return user
引用:7085
生成JWT令牌:使用python-jose
生成包含用户ID和过期时间的令牌:
from jose import jwt
from datetime import datetime, timedelta
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE = 30 # 分钟
def create_access_token(user_id: str) -> str:
payload = {"sub": user_id, "exp": datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE)}
return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
引用:8085
令牌解析:通过OAuth2PasswordBearer
定义令牌获取方式,并验证有效性:
from fastapi.security import OAuth2PasswordBearer
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="auth/login")
async def get_current_user(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
user_id = payload.get("sub")
user = db.query(User).filter(User.id == user_id).first()
if not user:
raise HTTPException(status_code=401, detail="无效令牌")
return user
except JWTError:
raise HTTPException(status_code=401, detail="令牌过期或无效")
引用:5580
受保护路由:在需要登录的路由中添加Depends(get_current_user)
:
@router.get("/profile")
async def user_profile(current_user: User = Depends(get_current_user)):
return {"username": current_user.username}
@router.post("/login")
async def login(user: UserLoginSchema, db: Session = Depends(get_db)):
authenticated_user = await authenticate_user(user.username, user.password, db)
if not authenticated_user:
raise HTTPException(status_code=401, detail="用户名或密码错误")
token = create_access_token(str(authenticated_user.id))
return {"code": 200, "access_token": token, "token_type": "bearer"}
引用:70from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
engine = create_async_engine("mysql+aiomysql://user:password@localhost/db")
async def get_db():
async with AsyncSession(engine) as session:
yield session
引用:29安全性增强:
SECRET_KEY
。性能优化:
asyncpg
或aiomysql
)。扩展性设计:
APIRouter
拆分业务模块(用户、订单、商品)。app/
├── main.py # 主入口
├── routers/
│ ├── auth.py # 认证路由(注册/登录)
│ └── users.py # 用户信息路由
├── models/
│ └── user.py # 用户模型定义
├── schemas/
│ └── user.py # Pydantic数据模型
├── dependencies.py # 鉴权依赖项
└── utils/
├── security.py # JWT与密码工具
└── database.py # 数据库连接
引用整合:1295570778085以下是如何基于ThinkPHP6用户登录逻辑,结合FastAPI框架实现用户登录系统的全流程解析,涵盖路由配置、数据验证、JWT令牌生成与鉴权、中间件依赖等核心环节:
路由定义:使用APIRouter
组织用户认证相关接口(注册、登录),并通过app.include_router()
集成到主应用。例如:
# routers/auth.py
from fastapi import APIRouter
router = APIRouter(prefix="/auth", tags=["Authentication"])
@router.post("/register")
async def register(user: UserRegisterSchema):
...
@router.post("/login")
async def login(user: UserLoginSchema):
...
引用:2977
请求数据模型:通过Pydantic模型定义请求参数,实现数据校验与自动文档生成:
from pydantic import BaseModel
class UserLoginSchema(BaseModel):
username: str
password: str
引用:62
密码哈希存储:使用passlib
的bcrypt
算法加密密码,避免明文存储:
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def hash_password(password: str) -> str:
return pwd_context.hash(password)
引用:185
用户唯一性校验:注册时检查用户名是否已存在:
async def register(user: UserRegisterSchema, db: Session = Depends(get_db)):
existing_user = db.query(User).filter(User.username == user.username).first()
if existing_user:
raise HTTPException(status_code=400, detail="用户已存在")
hashed_pwd = hash_password(user.password)
db_user = User(username=user.username, password=hashed_pwd)
db.add(db_user)
db.commit()
引用:1
身份验证:查询数据库并验证密码哈希:
def verify_password(plain_pwd: str, hashed_pwd: str) -> bool:
return pwd_context.verify(plain_pwd, hashed_pwd)
async def authenticate_user(username: str, password: str, db: Session):
user = db.query(User).filter(User.username == username).first()
if not user or not verify_password(password, user.password):
return None
return user
引用:7085
生成JWT令牌:使用python-jose
生成包含用户ID和过期时间的令牌:
from jose import jwt
from datetime import datetime, timedelta
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE = 30 # 分钟
def create_access_token(user_id: str) -> str:
payload = {"sub": user_id, "exp": datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE)}
return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
引用:8085
令牌解析:通过OAuth2PasswordBearer
定义令牌获取方式,并验证有效性:
from fastapi.security import OAuth2PasswordBearer
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="auth/login")
async def get_current_user(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
user_id = payload.get("sub")
user = db.query(User).filter(User.id == user_id).first()
if not user:
raise HTTPException(status_code=401, detail="无效令牌")
return user
except JWTError:
raise HTTPException(status_code=401, detail="令牌过期或无效")
引用:5580
受保护路由:在需要登录的路由中添加Depends(get_current_user)
:
@router.get("/profile")
async def user_profile(current_user: User = Depends(get_current_user)):
return {"username": current_user.username}
@router.post("/login")
async def login(user: UserLoginSchema, db: Session = Depends(get_db)):
authenticated_user = await authenticate_user(user.username, user.password, db)
if not authenticated_user:
raise HTTPException(status_code=401, detail="用户名或密码错误")
token = create_access_token(str(authenticated_user.id))
return {"code": 200, "access_token": token, "token_type": "bearer"}
引用:70from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
engine = create_async_engine("mysql+aiomysql://user:password@localhost/db")
async def get_db():
async with AsyncSession(engine) as session:
yield session
引用:29安全性增强:
SECRET_KEY
。性能优化:
asyncpg
或aiomysql
)。扩展性设计:
APIRouter
拆分业务模块(用户、订单、商品)。app/
├── main.py # 主入口
├── routers/
│ ├── auth.py # 认证路由(注册/登录)
│ └── users.py # 用户信息路由
├── models/
│ └── user.py # 用户模型定义
├── schemas/
│ └── user.py # Pydantic数据模型
├── dependencies.py # 鉴权依赖项
└── utils/
├── security.py # JWT与密码工具
└── database.py # 数据库连接