解决登录和oss问题

This commit is contained in:
andy committed 2026-08-28 09:52:11 +08:00
1 parent 30c2e44dc0
commit cd007e2f6a
15 files changed
+154 -12

No files matched your search

+1
View File
@@ -24,6 +24,7 @@ class Settings(BaseSettings):
oss_access_key_id: str | None = Field(default=None)
oss_access_key_secret: str | None = Field(default=None)
oss_endpoint: str | None = Field(default=None)
oss_public_base_url: str | None = Field(default=None)
oss_bucket_name: str | None = Field(default=None)
wechat_miniapp_appid: str | None = Field(default=None)
wechat_miniapp_secret: str | None = Field(default=None)
+29 -3
View File
@@ -24,6 +24,24 @@ def normalized_oss_host(endpoint: str, bucket: str) -> tuple[str, str]:
return parsed.scheme, host
def normalized_public_base_url(base_url: str) -> tuple[str, str]:
raw = base_url.strip().rstrip("/")
if "://" not in raw:
raw = f"https://{raw}"
parsed = urlsplit(raw)
if (
parsed.scheme not in {"http", "https"}
or not parsed.netloc
or parsed.username
or parsed.password
or parsed.path not in {"", "/"}
or parsed.query
or parsed.fragment
):
raise ValueError("invalid OSS public base URL")
return parsed.scheme, parsed.netloc
def sign_oss_get_url(
url: str,
*,
@@ -32,10 +50,17 @@ def sign_oss_get_url(
endpoint: str,
bucket: str,
expires_at: int,
public_base_url: str | None = None,
) -> str:
scheme, expected_host = normalized_oss_host(endpoint, bucket)
source_scheme, source_host = normalized_oss_host(endpoint, bucket)
public_scheme, public_host = (
normalized_public_base_url(public_base_url)
if public_base_url and public_base_url.strip()
else (source_scheme, source_host)
)
parsed = urlsplit(url)
if parsed.scheme != scheme or parsed.netloc.lower() != expected_host.lower():
configured_hosts = {source_host.lower(), public_host.lower()}
if parsed.scheme not in {"http", "https"} or parsed.netloc.lower() not in configured_hosts:
return url
path = parsed.path or "/"
@@ -60,7 +85,7 @@ def sign_oss_get_url(
("Signature", signature),
]
)
return urlunsplit((scheme, expected_host, path, urlencode(query), ""))
return urlunsplit((public_scheme, public_host, path, urlencode(query), ""))
def resolve_media_url(url: str | None) -> str | None:
@@ -85,6 +110,7 @@ def resolve_media_url(url: str | None) -> str | None:
endpoint=settings.oss_endpoint,
bucket=settings.oss_bucket_name,
expires_at=int(time()) + MEDIA_URL_EXPIRES_SECONDS,
public_base_url=getattr(settings, "oss_public_base_url", None),
)
except (TypeError, ValueError):
return url
+4 -2
View File
@@ -182,6 +182,8 @@ class InMemoryAdminSessionStore:
class RedisAdminSessionStore:
prefix = "wonderq:admin"
# WATCH/MULTI/EXEC requires every transaction key to share one Redis Cluster slot.
session_slot_tag = "{wonderq-admin-session}"
def __init__(self) -> None:
try:
@@ -194,10 +196,10 @@ class RedisAdminSessionStore:
raise RedisUnavailableError("Redis 会话存储不可用") from exc
def _session_key(self, session_id: str) -> str:
return f"{self.prefix}:session:{session_id}"
return f"{self.prefix}:{self.session_slot_tag}:session:{session_id}"
def _refresh_key(self, refresh_hash: str) -> str:
return f"{self.prefix}:refresh:{refresh_hash}"
return f"{self.prefix}:{self.session_slot_tag}:refresh:{refresh_hash}"
def _permission_key(self, user_id: str) -> str:
return f"{self.prefix}:permission:{user_id}"
+7 -3
View File
@@ -58,7 +58,7 @@ from ..schemas import (
DetailPatch,
)
from ..seed import create_media
from ..media_urls import resolve_media_url
from ..media_urls import normalized_public_base_url, resolve_media_url
from ..serializers import concierge_advisor_dict, detail_record_dict, encode_value, lead_dict, media_model_dict, model_dict
from .shared import site_config
@@ -168,6 +168,7 @@ def oss_settings():
"OSS_ACCESS_KEY_ID": settings.oss_access_key_id,
"OSS_ACCESS_KEY_SECRET": settings.oss_access_key_secret,
"OSS_ENDPOINT": settings.oss_endpoint,
"OSS_PUBLIC_BASE_URL": settings.oss_public_base_url,
"OSS_BUCKET_NAME": settings.oss_bucket_name,
}
missing = [key for key, value in values.items() if not (value and value.strip())]
@@ -193,6 +194,10 @@ def upload_image_to_oss(file_obj, key: str, mime_type: str, size_bytes: int) ->
settings = oss_settings()
bucket = settings.oss_bucket_name.strip()
scheme, host = normalized_oss_host(settings.oss_endpoint, bucket)
try:
public_scheme, public_host = normalized_public_base_url(settings.oss_public_base_url)
except (TypeError, ValueError):
media_error(503, "OSS 公网访问地址配置不正确", "MEDIA_STORAGE_INVALID_PUBLIC_URL")
date = formatdate(usegmt=True)
canonical_resource = f"/{bucket}/{key}"
string_to_sign = f"PUT\n\n{mime_type}\n{date}\n{canonical_resource}"
@@ -219,7 +224,7 @@ def upload_image_to_oss(file_obj, key: str, mime_type: str, size_bytes: int) ->
media_error(502, "OSS 上传失败", "MEDIA_STORAGE_UPLOAD_FAILED")
finally:
connection.close()
return urlunsplit((scheme, host, f"/{quoted_key}", "", ""))
return urlunsplit((public_scheme, public_host, f"/{quoted_key}", "", ""))
def audit(db: Session, actor_id: str | None, action: str, entity: str, entity_id: str | None = None, after=None, before=None) -> None:
@@ -1551,4 +1556,3 @@ def upload_media_asset(
db.commit()
return success_response(media_model_dict(asset), status_code=status.HTTP_201_CREATED)