fix license check

This commit is contained in:
2026-08-03 15:18:28 +08:00
parent 2090597858
commit bae71f3253
11 changed files with 469 additions and 20 deletions
+35 -18
View File
@@ -41,8 +41,8 @@ Ue6JWRU4j3Wg37WDPbwkO3tQba2jbUQsLYomLGuohfkVAgMBAAE=
-----END PUBLIC KEY-----"""
# {{LICENSE_PUBLIC_KEY_END}}
# 许可证文件相对路径
LICENSE_FILE = "license.lic"
# 许可证文件检索模式(默认在程序目录中匹配)
LICENSE_GLOB = "*license.lic"
# 巡检间隔(分钟)
DEFAULT_CHECK_INTERVAL = 5
@@ -164,11 +164,38 @@ def _validate_payload(payload):
return has_new_format
def _default_license_dir():
"""返回默认许可证搜索目录。"""
# PyInstaller 打包后 sys.executable 是 exe 路径
return Path(sys.executable).parent if getattr(sys, 'frozen', False) else Path.cwd()
def _resolve_license_path(lic_path=None):
"""解析许可证路径。
- 显式传入 ``lic_path`` 时直接使用该路径。
- 未传入时,在默认目录按 ``*license.lic`` 匹配,优先选择最近修改的文件。
"""
if lic_path is not None:
return Path(lic_path)
search_dir = _default_license_dir()
matches = [path for path in search_dir.glob(LICENSE_GLOB) if path.is_file()]
if not matches:
raise FileNotFoundError(
f"未找到许可证文件(模式: {LICENSE_GLOB},目录: {search_dir})"
)
# 多个候选时优先取最新文件;同修改时间再按文件名稳定排序。
matches.sort(key=lambda path: (path.stat().st_mtime, path.name), reverse=True)
return matches[0]
def verify_license(lic_path=None):
"""验证许可证签名 + 有效期。
Args:
lic_path: 许可证文件路径,默认 exe 同级目录下的 license.lic
lic_path: 许可证文件路径,默认在程序目录按 *license.lic 自动匹配
Returns:
dict: 许可证 payloadcustomer, expiry, issued 等)
@@ -179,10 +206,7 @@ def verify_license(lic_path=None):
RuntimeError: 许可证已过期
ValueError: 许可证格式错误
"""
if lic_path is None:
# PyInstaller 打包后 sys.executable 是 exe 路径
exe_dir = Path(sys.executable).parent if getattr(sys, 'frozen', False) else Path.cwd()
lic_path = exe_dir / LICENSE_FILE
lic_path = _resolve_license_path(lic_path)
if not os.path.exists(lic_path):
raise FileNotFoundError(f"许可证文件不存在: {lic_path}")
@@ -531,7 +555,7 @@ def check_license(lic_path=None):
"""启动时调用:验证许可证,通过则返回 payload。
在 main.py 的 main() 函数开头调用一次即可。
内部会自动启动后台巡检线程。
仅启动时执行校验,不自动启动后台巡检线程。
Returns:
dict: 许可证载荷
@@ -549,7 +573,6 @@ def check_license(lic_path=None):
with _verified_license_lock:
global _verified_license
_verified_license = dict(payload)
start_license_watchdog()
expiry = payload.get("expiry", "未知")
customer = payload.get("customer", "未知")
_log(f"✅ 许可证有效 | 客户: {customer} | 到期: {expiry}")
@@ -559,7 +582,7 @@ def check_license(lic_path=None):
_log(f"{e}")
_show_error_and_exit(
"未找到许可证文件",
"请将 license.lic 放到软件根目录,然后重新启动程序。\n\n"
"请将许可证文件放到软件根目录(文件名需匹配 *license.lic,然后重新启动程序。\n\n"
"如有疑问,请联系厂商获取有效的许可证文件。"
)
@@ -568,7 +591,7 @@ def check_license(lic_path=None):
_show_error_and_exit(
"许可证验证失败",
"许可证签名校验不通过,文件可能已被篡改。\n\n"
"请使用原始签发license.lic 文件,\n"
"请使用原始签发且文件名匹配 *license.lic 的许可证文件,\n"
"或联系厂商重新签发。"
)
@@ -626,13 +649,7 @@ def get_license_info(lic_path=None):
dict | None: 许可证信息,文件不存在则返回 None
"""
try:
if lic_path is None:
exe_dir = (
Path(sys.executable).parent
if getattr(sys, 'frozen', False)
else Path.cwd()
)
lic_path = exe_dir / LICENSE_FILE
lic_path = _resolve_license_path(lic_path)
if not os.path.exists(lic_path):
return None