本次提交完成了用户认证模块的注册扩展: 1. 新增阿里云短信和异步邮件发送工具类 2. 新增短信/邮箱相关配置类与环境变量支持 3. 添加短信验证码、待注册数据的Redis缓存工具方法 4. 扩展用户登录逻辑,支持用户名/邮箱/手机号多方式登录 5. 实现手机短信注册和邮箱验证注册完整流程 6. 更新权限初始化数据与系统配置项 7. 补充相关Pydantic请求响应模型 8. 新增依赖包并完善requirements.txt
81 lines
2.3 KiB
Python
81 lines
2.3 KiB
Python
import redis.asyncio as redis
|
|
from config import redis_settings
|
|
|
|
# 创建Redis连接池
|
|
redis_pool = redis.ConnectionPool.from_url(
|
|
redis_settings.url,
|
|
decode_responses=True
|
|
)
|
|
|
|
|
|
async def get_redis():
|
|
"""获取Redis连接"""
|
|
async with redis.Redis(connection_pool=redis_pool) as conn:
|
|
try:
|
|
yield conn
|
|
finally:
|
|
await conn.close()
|
|
|
|
|
|
async def set_token_in_redis(redis_conn, user_id: int, token: str, expire_seconds: int):
|
|
"""将令牌存储到Redis"""
|
|
key = f"user:token:{user_id}"
|
|
await redis_conn.set(key, token, ex=expire_seconds)
|
|
|
|
|
|
async def get_token_from_redis(redis_conn, user_id: int):
|
|
"""从Redis获取令牌"""
|
|
key = f"user:token:{user_id}"
|
|
return await redis_conn.get(key)
|
|
|
|
|
|
async def delete_token_from_redis(redis_conn, user_id: int):
|
|
"""从Redis删除令牌"""
|
|
key = f"user:token:{user_id}"
|
|
await redis_conn.delete(key)
|
|
|
|
|
|
async def check_token_in_redis(redis_conn, user_id: int, token: str):
|
|
"""检查令牌是否在Redis中且有效"""
|
|
stored_token = await get_token_from_redis(redis_conn, user_id)
|
|
return stored_token == token
|
|
|
|
|
|
# ========================================
|
|
# 注册相关:短信验证码
|
|
# ========================================
|
|
|
|
|
|
async def save_sms_code(redis_conn, phone: str, code: str, expire_seconds: int = 300):
|
|
"""存储短信验证码"""
|
|
key = f"sms_code:{phone}"
|
|
await redis_conn.set(key, code, ex=expire_seconds)
|
|
|
|
|
|
async def get_and_delete_sms_code(redis_conn, phone: str) -> str | None:
|
|
"""获取并删除短信验证码(一次性使用)"""
|
|
key = f"sms_code:{phone}"
|
|
code = await redis_conn.get(key)
|
|
if code:
|
|
await redis_conn.delete(key)
|
|
return code
|
|
|
|
|
|
# ========================================
|
|
# 注册相关:待注册数据(邮箱验证)
|
|
# ========================================
|
|
|
|
|
|
async def save_pending_registration(redis_conn, token_id: str, data: str, expire_seconds: int = 1800):
|
|
"""存储待注册数据"""
|
|
key = f"reg_pending:{token_id}"
|
|
await redis_conn.set(key, data, ex=expire_seconds)
|
|
|
|
|
|
async def get_and_delete_pending_registration(redis_conn, token_id: str) -> str | None:
|
|
"""获取并删除待注册数据(一次性使用)"""
|
|
key = f"reg_pending:{token_id}"
|
|
data = await redis_conn.get(key)
|
|
if data:
|
|
await redis_conn.delete(key)
|
|
return data |