修复登录
This commit is contained in:
@@ -25,7 +25,7 @@ HUB_TRUST_LAN=true
|
|||||||
# HUB_PASSWORD=your-strong-password-here
|
# HUB_PASSWORD=your-strong-password-here
|
||||||
# 会话签名密钥(建议单独随机串;未设则用用户名+密码拼接)
|
# 会话签名密钥(建议单独随机串;未设则用用户名+密码拼接)
|
||||||
# HUB_SESSION_SECRET=another-long-random-string
|
# HUB_SESSION_SECRET=another-long-random-string
|
||||||
# HTTPS 反代时设为 true,Cookie 仅通过加密连接传输
|
# HTTPS 反代时建议 true:仅 HTTPS 访问会带 Secure Cookie;http://内网IP:5100 仍可登录
|
||||||
# HUB_COOKIE_SECURE=true
|
# HUB_COOKIE_SECURE=true
|
||||||
# 登录保持天数(默认 7)
|
# 登录保持天数(默认 7)
|
||||||
# HUB_SESSION_DAYS=7
|
# HUB_SESSION_DAYS=7
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ from settings_store import (
|
|||||||
from hub_web_auth import (
|
from hub_web_auth import (
|
||||||
SESSION_COOKIE,
|
SESSION_COOKIE,
|
||||||
SESSION_MAX_AGE_SEC,
|
SESSION_MAX_AGE_SEC,
|
||||||
cookie_secure,
|
cookie_secure_for_request,
|
||||||
create_session_token,
|
create_session_token,
|
||||||
is_public_path,
|
is_public_path,
|
||||||
password_required,
|
password_required,
|
||||||
@@ -160,12 +160,13 @@ def api_auth_status(request: Request):
|
|||||||
|
|
||||||
|
|
||||||
@app.post("/api/auth/login")
|
@app.post("/api/auth/login")
|
||||||
def api_auth_login(body: LoginBody):
|
def api_auth_login(body: LoginBody, request: Request):
|
||||||
if not password_required():
|
if not password_required():
|
||||||
return {"ok": True, "auth_disabled": True}
|
return {"ok": True, "auth_disabled": True}
|
||||||
if not verify_credentials(body.username, body.password):
|
if not verify_credentials(body.username, body.password):
|
||||||
raise HTTPException(status_code=401, detail="用户名或密码错误")
|
raise HTTPException(status_code=401, detail="用户名或密码错误")
|
||||||
token = create_session_token(body.username)
|
token = create_session_token(body.username)
|
||||||
|
secure = cookie_secure_for_request(request)
|
||||||
resp = JSONResponse({"ok": True})
|
resp = JSONResponse({"ok": True})
|
||||||
resp.set_cookie(
|
resp.set_cookie(
|
||||||
SESSION_COOKIE,
|
SESSION_COOKIE,
|
||||||
@@ -174,15 +175,16 @@ def api_auth_login(body: LoginBody):
|
|||||||
samesite="lax",
|
samesite="lax",
|
||||||
path="/",
|
path="/",
|
||||||
max_age=SESSION_MAX_AGE_SEC,
|
max_age=SESSION_MAX_AGE_SEC,
|
||||||
secure=cookie_secure(),
|
secure=secure,
|
||||||
)
|
)
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|
||||||
@app.post("/api/auth/logout")
|
@app.post("/api/auth/logout")
|
||||||
def api_auth_logout():
|
def api_auth_logout(request: Request):
|
||||||
|
secure = cookie_secure_for_request(request)
|
||||||
resp = JSONResponse({"ok": True})
|
resp = JSONResponse({"ok": True})
|
||||||
resp.delete_cookie(SESSION_COOKIE, path="/")
|
resp.delete_cookie(SESSION_COOKIE, path="/", secure=secure)
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -92,8 +92,30 @@ def validate_session_token(token: str | None) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def cookie_secure() -> bool:
|
def cookie_secure_env_enabled() -> bool:
|
||||||
return (os.getenv("HUB_COOKIE_SECURE") or "").strip().lower() in ("1", "true", "yes", "on")
|
"""是否在 .env 中启用「HTTPS 时带 Secure Cookie」策略。"""
|
||||||
|
return (os.getenv("HUB_COOKIE_SECURE") or "").strip().lower() in (
|
||||||
|
"1",
|
||||||
|
"true",
|
||||||
|
"yes",
|
||||||
|
"on",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def cookie_secure_for_request(request) -> bool:
|
||||||
|
"""
|
||||||
|
仅在实际 HTTPS 访问时设置 Secure Cookie。
|
||||||
|
这样可同时支持:域名 HTTPS 反代 + 内网 http://IP:5100 登录。
|
||||||
|
"""
|
||||||
|
if not cookie_secure_env_enabled():
|
||||||
|
return False
|
||||||
|
proto = (
|
||||||
|
(request.headers.get("x-forwarded-proto") or request.url.scheme or "http")
|
||||||
|
.split(",")[0]
|
||||||
|
.strip()
|
||||||
|
.lower()
|
||||||
|
)
|
||||||
|
return proto == "https"
|
||||||
|
|
||||||
|
|
||||||
def is_public_path(path: str, method: str) -> bool:
|
def is_public_path(path: str, method: str) -> bool:
|
||||||
|
|||||||
@@ -277,7 +277,8 @@ python hub.py
|
|||||||
| 无关键位块 | 该户 capabilities 无 `key` | 正常;Gate 趋势户无关键位 |
|
| 无关键位块 | 该户 capabilities 无 `key` | 正常;Gate 趋势户无关键位 |
|
||||||
| 局域网无法打开中控 | 防火墙 / `HUB_TRUST_LAN=0` | 放行端口或恢复默认信任私网 |
|
| 局域网无法打开中控 | 防火墙 / `HUB_TRUST_LAN=0` | 放行端口或恢复默认信任私网 |
|
||||||
| 打开即跳转登录 | 已设 `HUB_PASSWORD` | 正常;输入密码后 7 天内免登(可改 `HUB_SESSION_DAYS`) |
|
| 打开即跳转登录 | 已设 `HUB_PASSWORD` | 正常;输入密码后 7 天内免登(可改 `HUB_SESSION_DAYS`) |
|
||||||
| 登录后仍 401 | Cookie 未带上 / HTTPS | HTTPS 反代设 `HUB_COOKIE_SECURE=true` |
|
| 域名能登录、IP:5100 不能 | `HUB_COOKIE_SECURE=true` 且用 http 访问 IP | 已改为仅 HTTPS 才发 Secure Cookie;或 IP 用 http、域名用 https 各登一次 |
|
||||||
|
| 登录后仍 401 | Cookie 未带上 | 反代需传 `X-Forwarded-Proto: https`;勿混用不同主机名的 Cookie |
|
||||||
|
|
||||||
手动探测实例桥接:
|
手动探测实例桥接:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user