fix(fam-core): 登录密码不再硬编码兜底(fail-closed) + 会话有效期改 2 小时
之前 FAM_AUTH_USER/FAM_AUTH_PASS 没配置时会退回代码里写死的 ericwyuan/ iLoveJava5——这两个值跟 NAS SSH 密码是同一个,且这个登录页已经通过 frp 暴露在 公网上。.env 万一没配置好(这个项目里已经发生过好几次"忘了 source .env"的 情况),公网入口就会用一个和 SSH 密码相同、且写在源码里的已知密码兜底,双重 风险叠一起。 现在改成 fail-closed:FAM_AUTH_USER/FAM_AUTH_PASS 只要有一个没配置,直接拒绝 所有登录(打一条 ERROR 日志提醒去配 .env),不再有任何硬编码默认值。 会话有效期从 7 天改成 2 小时(按用户要求)。 新增 test_auth.py 11 个用例覆盖:未配置时 fail-closed、正确/错误凭据校验、 只配了一半也要拒绝、session 过期判定、白名单路径匹配。 已实测验证:当前 .env 里 FAM_AUTH_USER/PASS 仍是配置好的(还是 ericwyuan/ iLoveJava5,这个值本身没改——只是不再硬编码在代码里,运维如果想换成不同于 SSH 的密码,现在改 .env 就行,不用改代码),登录/拒绝错误密码都验证正常, cookie Max-Age=7200 确认生效。
This commit is contained in:
@@ -3,9 +3,12 @@ Auth - FAM-Core 登录校验(2026-08-22 新增)
|
||||
|
||||
背景:NAS :8000(fam-core + FAM-UI)通过 frp 暴露到外网后,需要先登录才能访问。
|
||||
|
||||
- 账号密码:环境变量 FAM_AUTH_USER / FAM_AUTH_PASS(默认 ericwyuan / iLoveJava5),
|
||||
由 NAS 的 start_core.sh source .env 注入。
|
||||
- 登录态:进程内 token 表 + HttpOnly cookie(fam_session),默认 7 天有效;
|
||||
- 账号密码:环境变量 FAM_AUTH_USER / FAM_AUTH_PASS,由 NAS 的 start_core.sh
|
||||
source .env 注入。2026-08-23 起不再提供硬编码默认值——这两个环境变量跟
|
||||
NAS SSH 密码是同一个值,公网入口用同一串密码兜底、还写死在代码里是双重
|
||||
风险;.env 没配置好这两个变量时,直接拒绝所有登录(fail closed),而不是
|
||||
悄悄退回一个大家都知道的密码。
|
||||
- 登录态:进程内 token 表 + HttpOnly cookie(fam_session),2 小时有效;
|
||||
重启进程后需重新登录(可接受,见 config/auth 说明)。
|
||||
- 拦截策略(app.before_request 全局生效):
|
||||
* 页面路径未登录 -> 302 重定向 /login
|
||||
@@ -23,16 +26,31 @@ import time
|
||||
from flask import (Blueprint, Response, jsonify, make_response,
|
||||
redirect, request)
|
||||
|
||||
from .logger import setup_logger
|
||||
|
||||
logger = setup_logger('fam-core.auth')
|
||||
|
||||
auth_bp = Blueprint('auth', __name__)
|
||||
|
||||
_SESSION_TTL = 7 * 24 * 3600 # cookie 有效期 7 天
|
||||
_SESSION_TTL = 2 * 3600 # cookie 有效期 2 小时
|
||||
_sessions = {} # token -> 过期时间戳(进程内;重启需重新登录)
|
||||
_warned_unconfigured = False # 只在第一次拒绝登录时打一条警告日志,别刷屏
|
||||
|
||||
|
||||
def _check_credential(username: str, password: str) -> bool:
|
||||
"""账号密码校验。凭据从环境变量读(.env 注入),未设置用默认值。"""
|
||||
user = os.environ.get('FAM_AUTH_USER', 'ericwyuan')
|
||||
pwd = os.environ.get('FAM_AUTH_PASS', 'iLoveJava5')
|
||||
"""账号密码校验。凭据必须从环境变量读(.env 注入),不提供硬编码默认值——
|
||||
这两个变量跟 NAS SSH 密码是同一个值,公网入口不能有"没配置就退回已知密码"
|
||||
这种兜底,宁可直接拒绝所有登录(fail closed),等运维发现并配置好 .env。"""
|
||||
global _warned_unconfigured
|
||||
user = os.environ.get('FAM_AUTH_USER', '')
|
||||
pwd = os.environ.get('FAM_AUTH_PASS', '')
|
||||
if not user or not pwd:
|
||||
if not _warned_unconfigured:
|
||||
logger.error(
|
||||
"FAM_AUTH_USER/FAM_AUTH_PASS 未配置,拒绝所有登录——"
|
||||
"请在 .env 里设置这两个环境变量后重启 fam-core")
|
||||
_warned_unconfigured = True
|
||||
return False
|
||||
return (username or '') == user and (password or '') == pwd
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user