Add Redis-based one-time download token support

Integrate Redis as a backend for one-time download token validation, with in-memory fallback. Added RedisManager for connection lifecycle, TokenStore for atomic token usage checks, and related configuration via environment variables. Updated download flow to ensure tokens are single-use, and improved API robustness for batch operations. Updated dependencies to include redis and cachetools.
This commit is contained in:
2025-12-26 18:47:46 +08:00
parent 3088a9d548
commit d8a229fccd
13 changed files with 302 additions and 15 deletions

View File

@@ -1,5 +1,5 @@
from datetime import datetime, timedelta, timezone
from uuid import UUID
from uuid import UUID, uuid4
import jwt
from fastapi.security import OAuth2PasswordBearer
@@ -108,13 +108,14 @@ DOWNLOAD_TOKEN_TTL = timedelta(hours=1)
def create_download_token(file_id: UUID, owner_id: UUID) -> str:
"""
创建文件下载令牌。
创建一次性文件下载令牌。
:param file_id: 文件 ID
:param owner_id: 文件所有者 ID
:return: JWT 令牌字符串
"""
payload = {
"jti": str(uuid4()),
"file_id": str(file_id),
"owner_id": str(owner_id),
"exp": datetime.now(timezone.utc) + DOWNLOAD_TOKEN_TTL,

View File

@@ -1,2 +1,3 @@
from .password.pwd import Password, PasswordStatus
from .http import http_exceptions
from .http import http_exceptions
from .conf import appmeta

View File

@@ -11,14 +11,36 @@ description = 'DiskNext Server 是一款基于 FastAPI 的网盘系统,支持
license_info = {"name": "GPLv3", "url": "https://opensource.org/license/gpl-3.0"}
BackendVersion = "0.0.1"
"""后端版本"""
IsPro = False
mode: str = os.getenv('MODE', 'master')
"""运行模式"""
debug: bool = os.getenv("DEBUG", "false").lower() in ("true", "1", "yes") or False
"""是否启用调试模式"""
if debug:
log.warning("Debug mode is enabled. This is not recommended for production use.")
database_url: str = os.getenv("DATABASE_URL", "sqlite+aiosqlite:///disknext.db")
database_url: str = os.getenv("DATABASE_URL", "sqlite+aiosqlite:///disknext.db")
"""数据库地址"""
redis_url: str | None = os.getenv("REDIS_URL")
"""Redis 主机地址"""
_redis_port = os.getenv("REDIS_PORT")
redis_port: int = int(_redis_port) if _redis_port else 6379
"""Redis 端口,默认 6379"""
redis_password: str | None = os.getenv("REDIS_PASSWORD")
"""Redis 密码"""
_redis_db = os.getenv("REDIS_DB")
redis_db: int = int(_redis_db) if _redis_db else 0
"""Redis 数据库索引,默认 0"""
_redis_protocol = os.getenv("REDIS_PROTOCOL")
redis_protocol: int = int(_redis_protocol) if _redis_protocol else 3
"""Redis 协议版本,默认 3"""