| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 |
- """面板鉴权:itsdangerous 签名 Cookie。
- 密码来源优先级:环境变量 LARK_PANEL_PASSWORD > config.panel.password。
- 未设置密码时面板无法登录(拒绝空密码)。
- """
- from __future__ import annotations
- import os
- import time
- from typing import Optional
- from itsdangerous import BadSignature, SignatureExpired, URLSafeTimedSerializer
- COOKIE_NAME = "lark2lark_session"
- COOKIE_MAX_AGE = 7 * 24 * 3600 # 7 天
- def _get_secret_key(panel_password: str) -> str:
- """用面板密码派生签名密钥(固定 salt 保证进程间一致)。"""
- # 密码本身就是准入凭据,直接作为签名密钥源;加固定前缀防止空密码
- return f"lark2lark::{panel_password}"
- def has_password(panel_password: str) -> bool:
- return bool(panel_password and panel_password.strip())
- def sign_session(panel_password: str) -> str:
- """登录成功后签发会话 token。"""
- serializer = URLSafeTimedSerializer(_get_secret_key(panel_password), salt="session")
- return serializer.dumps({"login_at": int(time.time())})
- def verify_session(token: str, panel_password: str) -> bool:
- """校验会话 token。失败返回 False。"""
- if not token:
- return False
- serializer = URLSafeTimedSerializer(_get_secret_key(panel_password), salt="session")
- try:
- serializer.loads(token, max_age=COOKIE_MAX_AGE)
- return True
- except (BadSignature, SignatureExpired):
- return False
- def verify_password(input_password: str, expected_password: str) -> bool:
- """恒定时间比较,防侧信道计时攻击。"""
- if not expected_password:
- return False
- import hmac
- return hmac.compare_digest(input_password or "", expected_password)
|