账号密码登录:一次从界面到 CLI 的实操记录一、界面只保留账号,不写入密码密码框使用 tk.StringVar() 接收输入。开发者把 show 参数去掉后,密码框用明文显示内容。程序保存配置时只写入 username 和 appId。开发者关闭程序后,密码变量随进程释放,配置文件里没有密码字段。密码框代码:D:\J盘-杂料\业务资料\RPA项目资料

扫码分享
二维码

详细介绍

账号密码登录:一次从界面到 CLI 的实操记录

一、界面只保留账号,不写入密码

密码框使用 tk.StringVar() 接收输入。开发者把 show 参数去掉后,密码框用明文显示内容。

程序保存配置时只写入 username 和 appId。开发者关闭程序后,密码变量随进程释放,配置文件里没有密码字段。

密码框代码:D:\J盘-杂料\业务资料\RPA项目资料\网站RPA应用市场\成品系统\影刀应用解码+打包+脱机运行\yingdao_run_hider\yingdao_launcher.py:516

二、点击“登录/刷新列表”后,界面先转入后台线程

refresh_apps() 读取账号输入框和密码输入框,把两个值复制成局部变量。它禁用刷新按钮,再启动 refreshworker() 后台线程。

Tkinter 主线程继续处理窗口消息。后台线程执行隐藏器检查、客户端检查、登录和读取应用列表。后台线程执行完后,通过队列恢复按钮状态。

实现位置:yingdao_launcher.py:998

三、启动器先查当前账号

get_current_account() 执行:

shadowbot.shell-cli auth current

启动器读取返回 JSON 里的 loggedIn 和 userName。loggedIn 为 true 时,启动器拿到当前登录账号。

实现位置:yingdao_launcher.py:871

四、账号相同时,启动器直接使用当前会话

ensure_login() 先比较输入账号和当前账号。两个账号完全相同时,启动器记录“已登录”,然后返回。

这一步不重新校验密码。用户在已登录状态下填错密码,启动器仍会继续读取应用列表。

实现位置:yingdao_launcher.py:877

五、账号不同时,启动器先处理旧会话

账号不同时,启动器分三种情况处理。

第一种情况:用户没有填写密码。启动器记录警告,停止本次刷新,界面不切换账号。

第二种情况:启动模式为自动启动,账号不同且密码为空。启动器保留当前账号,继续读取应用列表。程序启动时的初始化使用这个分支。

第三种情况:用户填写了密码。启动器清空旧应用列表,结束旧客户端,隐藏启动新客户端,再登录输入账号。

失败分支集中在一个方法里,读代码时不用在多个文件之间跳转。

六、启动器用 taskkill 结束旧客户端

restart_client_for_login() 依次执行两条命令:

taskkill /F /T /IM ShadowBot.Shell.exe
taskkill /F /T /IM ShadowBot.exe

启动器每 0.5 秒检查一次进程,最多等待 20 秒。旧进程退出后,启动器记录“已退出”,再调用 ensure_client() 隐藏启动新客户端。

/T 会结束进程树。影刀客户端当时正在跑任务,任务进程会一起结束。

实现位置:yingdao_launcher.py:843

七、新客户端启动后,启动器再次查账号

ensure_client() 启动新的 ShadowBot.exe。客户端可能使用本机保存的密码自动登录。启动器重新执行 auth current,检查新会话是否已经登录目标账号。

新会话已经登录目标账号时,启动器直接返回。新会话没有登录目标账号时,启动器继续调用 CLI 登录。

这一步挡住了“旧账号退出后,直接读取空白列表”的情况。

八、启动器调用 CLI 登录

启动器组装以下参数:

shadowbot.shell-cli auth login --username <账号> --password <密码> --login-timeout 2m

--login-timeout 设为 2 分钟。Python 侧的 subprocess.run() 设为 150 秒超时。CLI 超过 150 秒没有返回,启动器记录“登录超时”,并结束本次刷新。

实现位置:yingdao_launcher.py:922

九、CLI 返回 ok 后,启动器再核对实际账号

CLI 返回 ok: true 后,启动器再执行一次 auth current。它把返回的实际用户名和输入账号转成小写,再比较一次。

实际用户名和输入账号不一致时,启动器记录“登录后账号校验失败”,停止刷新。实际用户名和输入账号一致时,启动器记录“登录完成”,继续读取应用列表。

CLI 返回失败时,启动器依次读取 error、message、stderr、stdout,把第一条可用信息写入日志。

十、登录完成后,启动器读取应用列表

load_apps() 执行:

shadowbot.shell-cli console app --page-size 200

启动器从 data.items 取出应用记录,把 appName 和 appId 填入下拉框。应用列表只保存当前账号的数据。

实现位置:yingdao_launcher.py:983

十一、我实际试了账号切换

我先让客户端登录账号 A。启动器读到 5 个应用。

我把界面账号改成账号 B,填入密码,点击“登录/刷新列表”。日志按以下顺序输出:

  1. 检测到账号切换。

  1. 清空旧应用列表。

  1. 关闭旧客户端。

  1. 旧客户端退出。

  1. 隐藏启动新客户端。

  1. 登录账号 B。

  1. 读取到 13 个应用。

我又切回账号 A,列表恢复为账号 A 的数据。

我单独启动了一次隐藏的 Tk 界面,读取三个 ttk.Entry 的 show 属性。三个值都是空字符串,密码框没有星号掩码。

我还没用错误密码跑完整界面测试。当前代码在 CLI 返回 ok 且实际用户名匹配后才继续。

十二、这个登录模块的几个坑

  • 密码作为 --password 参数传给 CLI。同一台机器上能读取进程命令行的人可以看到这段参数。当前实现只做到不把密码写进配置文件。

  • 账号相同时,启动器信任已经存在的会话,不再验证本次输入的密码。

  • 账号不同且密码为空时,启动器不会使用另一个账号的已保存密码,界面也不会切换。

  • taskkill /T 会结束影刀进程树,正在运行的任务会停止。

  • 普通权限的启动器结束管理员权限的影刀进程时,Windows 会拒绝 taskkill。开发者要让两个进程使用相同权限级别。

  • auth login 在已登录会话里可能返回“当前账号已登录”,CLI 不执行切换。启动器先结束旧客户端,再调用登录命令。

  • 开发者不要把真实账号密码写进源码、配置文件或测试日志。