ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

JumpServer Chrome 网页小应用(Web Applet)深度解析:Selenium 版本约束、账号代填机制与安全模式实现

JumpServer Chrome 网页小应用(Web Applet)深度解析:Selenium 版本约束、账号代填机制与安全模式实现 JumpServer Chrome 网页小应用Web Applet深度解析Selenium 版本约束、账号代填机制与安全模式实现【免费下载链接】jumpserverJumpServer is an open-source Privileged Access Management (PAM) platform that provides DevOps and IT teams with on-demand and secure access to SSH, RDP, Kubernetes, Database and RemoteApp endpoints through a web browser.项目地址: https://gitcode.com/GitHub_Trending/ju/jumpserverJumpServer 的 Chrome 小应用Applet是终端连接 Web 类资产的核心组件它在本地拉起真实 Chrome 浏览器借助 Selenium 自动完成登录页面的账号代填从而让用户在 Web 资产上也能获得与 SSH/RDP 一致的托管式访问体验。本文以 README_EN.md 为线索结合同目录下 app.py、main.py、common.py 等源码完整讲解其运行环境约束、代填两种模式、步骤指令集、安全模式扩展与本地调试方法。读完本文你将掌握该小应用从清单配置、参数传人到浏览器启动与进程清理的完整链路能够自行定位版本不匹配代填失败新标签页拦截等常见问题。一、Chrome 小应用在 JumpServer 中的定位在 JumpServer 的终端体系中apps/terminal/applets/目录存放着各类连接小应用Chrome 小应用即其中的 Web 浏览器应用。它由 manifest.yml 声明name: chrome display_name: {{ Chrome Browser | trans }} version: 1.3 comment: {{ Chrome Browser Open URL Page Address | trans }} author: JumpServer Team exec_type: python update_policy: always type: web tags: - web protocols: - httptype: web、protocols: http表明该小应用面向 Web 类资产通过 HTTP/HTTPS 打开页面地址exec_type: python表示它以 Python 程序执行入口即 main.pyupdate_policy: always表示小应用更新时始终覆盖安装version: 1.3与 ChangeLog 中的最新版本号一致。其基本工作模式为用户在 JumpServer Web 界面点击连接 Web 资产 → 终端组件将资产、账号、平台等信息以 Base64 编码的 JSON 传给小应用 → 小应用启动本地 ChromeSelenium 驱动→ 打开资产地址并自动完成登录代填 → 将浏览器窗口交给用户操作。二、运行环境约束Selenium 版本与 Chrome/ChromeDriver 匹配README_EN.md 对运行环境给出了两条明确约束Selenium 版本固定为 4.4.0Chrome 与 ChromeDriver 版本必须匹配ChromeDriver 需从官方下载渠道获取与本地 Chrome 主版本一致的驱动。这两条约束在小应用源码中均有对应体现。app.py 中启动浏览器的核心代码为self.service Service() # driver 的 console 终端框不显示 self.service.creationflags CREATE_NO_WINDOW self.driver webdriver.Chrome(optionsself._chrome_options, serviceself.service) self.driver.implicitly_wait(10)Service()默认会在本机寻找chromedriver因此若本机 Chrome 与 ChromeDriver 主版本不一致Selenium 会在创建webdriver.Chrome时直接抛出SessionNotCreatedException之类的错误。这是该小应用最常见的启动失败原因之一排查时应先用chromedriver --version与chrome --versionWindows 下可在chrome://version查看核对两者主版本号一致。从源码结构看该小应用的交互逻辑大量依赖 Selenium 的 WebDriver APIfind_element定位元素、send_keys输入、click点击、switch_to.frame切换 iframe、implicitly_wait设置隐式等待默认 10 秒这些都是 Selenium 4.x 的标准用法也解释了为什么版本被严格锁定在 4.4.0。三、小应用安装与版本演进setup.yml 与 ChangeLog与多数小应用一样Chrome 小应用通过 setup.yml 描述安装方式type: manual # exe, zip, manual source: arguments: destination: program: md5:type: manual表示该小应用不需要额外下载安装包直接以目录形式分发由 JumpServer 终端组件将整个chrome目录作为应用载体。版本历史记录在 ChangeLog可以清晰看到其能力演进脉络版本日期类型内容1.32025-07-25Bug 修复修复 Chrome 密码管理器弹窗的问题1.22025-05-30功能更新新增用户配置的语言支持默认使用系统当前语言1.12024-10-24功能优化优化快速点击造成页面卡住的问题1.02023-09-18Bug 修复移除窗口最小化避免造成部分页面元素定位失败0.92023-09-04功能优化进度条显示最大超时0.82023-08-16功能优化修复代填失败造成页面卡住的问题0.72023-07-28功能优化增加进度窗口隐藏代填操作0.62023-07-13功能优化优化 Chrome 插件拦截逻辑0.52023-07-06功能更新增加匿名用户的支持如果账号是匿名用户username 和 secret 则为空这些演进点密码管理器弹窗、语言支持、进度窗口、匿名账号、插件拦截等都直接对应 app.py 与 common.py 中的具体实现下文将逐一展开。四、输入数据Base64 JSON 与数据模型小应用通过命令行参数接收一次连接所需的所有上下文。main.py 的入口逻辑非常精简def main(): base64_str sys.argv[1] data convert_base64_to_dict(base64_str) applet_app AppletApplication(**data) block_input() applet_app.run() unblock_input() applet_app.wait()终端组件将连接参数序列化为 JSON 后再做 Base64 编码作为第一个命令行参数传入common.py 的convert_base64_to_dict负责解码并还原为 dict连接期间调用block_input()锁定用户键盘鼠标输入避免用户在自动代填过程中干扰页面操作代填完成后unblock_input()解锁。仓库提供了完整的调试样例 test_data_example.json展示了输入数据的完整结构{ protocol: web, user: { id: 2647CA35-5CAD-4DDF-8A88-6BD88F39BB30, name: Administrator, username: admin }, asset: { id: 46EE5F50-F1C1-468C-97EE-560E3436754C, name: test_baidu, address: https://www.baidu.com, category: { value: web, label: web }, protocols: [ { id: 2, name: http, port: 80 } ], specific: { autofill: basic, username_selector: nameusername, password_selector: namepassword, submit_selector: idlogin_button, script: [] } }, account: { id: 9D5585DE-5132-458C-AABE-89A83C112A83, name: test_mysql, username: root, secret: }, platform: { charset: UTF-8 } }对应的数据模型定义在 common.pyUser当前登录用户id/name/usernameAssetWeb 资产含address要打开的 URL、protocols、category与spec_info即样例中的specificWeb 类资产的代填配置Account代填账号含username、secret密码/密钥secret_type描述密钥类型Platform平台信息通过get_protocol_setting(http)可取到该协议下的默认代填设置ProtocolSettingConnectOption连接选项包含lang语言、charset等。Asset与Platform都提供了get_protocol_setting/get_protocol_port之类的便捷方法小应用据此决定以哪一套配置执行代填。五、账号自动代填basic 与 script 两种模式账号代填是 Chrome 小应用的核心能力实现在 app.py 的WebAPP类中。代填策略按优先级解析先看资产自身的spec_info.autofill若资产未配置则回退到平台的 HTTP 协议设置platform.get_protocol_setting(http).autofill。extra_data self.asset.spec_info autofill_type extra_data.autofill if not autofill_type: protocol_setting self.platform.get_protocol_setting(http) ... extra_data protocol_setting autofill_type extra_data.autofill5.1 basic 模式选择器三步代填当autofill basic时使用_default_custom_steps生成固定三步return [ Step({step: 1, value: self._account_username, target: spec_info.username_selector, command: type}), Step({step: 2, value: self._account_secret, target: spec_info.password_selector, command: type}), Step({step: 3, value: , target: spec_info.submit_selector, command: click}) ]对应平台/资产需配置三个选择器字段见 common.py 的Specific/ProtocolSettingusername_selector用户名输入框定位表达式password_selector密码输入框定位表达式submit_selector登录按钮定位表达式。样例中nameusername、idlogin_button的写法即定位方式值格式支持的定位方式见下文的指令集章节。5.2 script 模式步骤脚本与占位符当autofill script时使用资产/平台配置的脚本步骤script_list extra_data.script steps sorted(script_list, keylambda step_item: step_item.step) for item in steps: val item.value if val: val val.replace({USERNAME}, self._account_username) val val.replace({SECRET}, self._account_secret) item.value val self._steps.append(item)要点脚本按step字段升序执行适合登录流程复杂的页面如先输用户名、点下一步、再输密码、最后提交步骤的value中支持两个内置占位符{USERNAME}替换为账号用户名{SECRET}替换为账号密码/密钥每个Step包含step序号、target元素定位、command指令类型、value输入值。5.3 匿名账号支持对应 ChangeLog v0.5 的匿名用户特性当account.username ANON时用户名与密钥均置空代填步骤中的账号信息为空串app.py适用于无需登录即可访问的公开页面。六、步骤指令集type / click / open / code / select_frame / sleepStepActionapp.py是单步指令的执行器指令类型由Command枚举定义class Command(Enum): TYPE type CLICK click OPEN open CODE code SELECT_FRAME select_frame SLEEP sleep6.1 元素定位方式映射target采用方式值的字符串格式methods_map支持以下定位方式大小写不敏感写法底层 Selenium 定位namexxxBy.NAMEidxxxBy.IDclass_namexxxBy.CLASS_NAMEcssxxx/css_selectorxxxBy.CSS_SELECTORxpathxxxBy.XPATH未匹配到已知方式时回退为By.NAME。例如样例中的nameusername即按表单控件的name属性定位。6.2 各指令行为open打开地址url value or target为空则跳过等价于driver.get(url)type向定位到的元素send_keys(value)即输入账号/密码click对定位元素执行click()code弹出一个交互式输入对话框见下节CodeDialog用户输入内容后写入当前定位元素——适用于验证码等无法预填的字段select_frame切换到目标 iframetarget支持三种格式_switch_iframe的实现index1按索引切换index为负数时switch_to.default_content()回到顶层文档idxxx按 iframe 的 id 切换namexxx按 iframe 的 name 切换其他格式直接作为 frame 引用切换sleeptime.sleep(int(target))target无法转为整数时至少休眠 1 秒用于等待页面异步加载。每一步通过execute_action包装执行任一指令抛出异常都会返回False此时WebAPP.execute会调用notify_err_message弹出错误提示提示内容含失败的target与command并中止代填流程避免代填失败造成页面卡住对应 ChangeLog v0.8。七、浏览器启动参数与安全模式7.1 默认浏览器选项default_chrome_driver_optionsapp.py集中定义了 Chrome 启动参数options.add_argument(--start-maximized) # 忽略证书错误相关 options.add_argument(--ignore-ssl-errors) options.add_argument(--ignore-certificate-errors) options.add_argument(--ignore-certificate-errors-spki-list) options.add_argument(--allow-running-insecure-content) # 禁用开发者工具 options.add_argument(--disable-dev-tools) # 禁用 密码管理器弹窗 prefs { credentials_enable_service: False, profile.password_manager_enabled: False, intl.accept_languages: languag, } options.add_experimental_option(prefs, prefs) # chromedriver 退出后也不关闭浏览器 options.add_experimental_option(detach, True) options.add_experimental_option(excludeSwitches, [enable-automation])几个关键点与 ChangeLog 的 Bug 修复一一对应禁用密码管理器弹窗credentials_enable_service与profile.password_manager_enabled置为False正是 v1.3修复 Chrome 密码管理器弹窗问题的实现手段excludeSwitches: [enable-automation]去掉 Chrome 的自动化测试提示条detach: Truechromedriver 退出后浏览器进程不被连带关闭证书相关参数用于访问自签名证书的 HTTPS 页面。7.2 应用窗口与临时用户目录AppletApplication.__init__app.py中为本次连接创建独立配置self._tmp_user_dir tempfile.TemporaryDirectory() lang self.connect_option.lang if self.connect_option.lang else get_system_language() self._chrome_options default_chrome_driver_options(languaglang) self._chrome_options.add_argument(--app{}.format(self.asset.address)) self._chrome_options.add_argument(--user-data-dir{}.format(self._tmp_user_dir.name))--appurl让 Chrome 以应用窗口模式打开资产地址无地址栏/标签栏对应 v1.0移除窗口最小化避免页面元素定位失败的调整每次连接使用tempfile.TemporaryDirectory()生成的临时--user-data-dir隔离浏览器缓存与 Cookie连接结束后由close()清理。7.3 安全模式扩展当平台 HTTP 协议设置了safe_mode时小应用会加载内置浏览器扩展disable_new_tab_window_menumanifest.jsonif protocol_setting and protocol_setting.safe_mode: extension_paths load_extensions() self._chrome_options.add_argument(--load-extension{}.format(,.join(extension_paths)))扩展包含三个文件对应 v0.6优化 Chrome 插件拦截逻辑background.js监听标签页创建/更新事件拦截chrome://newtab/与所有chrome://页面当打开的新标签页与首个标签页域名不同按主域名比较取最后两段时直接chrome.tabs.remove关闭从而保证用户始终停留在被授权访问的站点content_script.js通过MutationObserver将所有a链接的target改为_self当前窗口打开、重写window.open强制当前页跳转、屏蔽右键菜单、拦截 F12 / F1 以及除 CtrlP/C/F/V 外的所有 Ctrl 组合键防止打开开发者工具扩展在页面加载完成document_end时注入权限仅申请tabs。八、交互体验细节输入锁定、进度条与语言支持8.1 全局输入锁定common.py 在 Windows 平台通过user32.BlockInput实现键盘鼠标锁定与解锁_blockInput ctypes.windll.user32.BlockInput _blockInput.argtypes [wintypes.BOOL] def block_input(): if _blockInput: _blockInput(True) def unblock_input(): if _blockInput: _blockInput(False)代填过程全程锁定输入防止用户在自动化操作期间误触页面code指令输入验证码时则临时unblock_input()再锁定。8.2 全屏进度条与最大超时code_dialog.py 提供了两类 UI 组件CodeDialog基于tkinter的单行输入对话框支持回车确认空输入会弹出 warning用于code指令的验证码等手动输入TkProgressBar全屏置顶的 indeterminate 进度条wait_max_time 3000 * 10即 30 秒。wrapper_progress_bar装饰器将其套在run()外层——在后台线程中执行浏览器启动与代填同时前台显示隐藏代填操作的全屏进度动画超时自动销毁窗口。这正是 ChangeLog v0.7增加进度窗口隐藏代填操作与 v0.9进度条显示最大超时的实现。class TkProgressBar(object): # 30s wait_max_time 3000 * 108.3 语言支持对应 v1.2新增用户配置的语言支持默认使用系统当前语言语言优先级为connect_option.lang用户在 JumpServer 连接配置中指定的语言→get_system_language()common.pyWindows 下读取GetUserDefaultUILanguage转换语言代码失败回退en_US。该语言同时作用于intl.accept_languages偏好浏览器接受语言--langlang启动参数Chrome 界面语言。九、连接生命周期进程监控与清理9.1 等待浏览器退出wait()app.py负责管理进程生命周期parent_id self.service.process.pid pids get_children_pids(parent_id) ... # 退出 chromedriver 进程等待所有子进程退出 self.service.stop() while True: time.sleep(5) for pid in pids_status: pids_status[pid] check_pid_alive(pid) ...先通过wmic查询 chromedriver 的子进程get_children_pidsWindows 专属停掉 chromedriver 服务但依赖detach选项让浏览器继续运行每 5 秒用tasklistcheck_pid_alive轮询所有子进程全部退出后wait结束小应用随之退出。9.2 关闭与清理close()调用driver.quit()关闭全部浏览器窗口并清理本次连接创建的临时用户数据目录_tmp_user_dir。十、本地调试与验证无需部署完整 JumpServer也可在装有 Python 3 Selenium 4.4.0 Chrome/ChromeDriver 的 Windows 机器上单独运行该小应用确认pip show selenium版本为 4.4.0确认chromedriver --version与 Chrome 主版本一致修改 test_data_example.json将asset.address换成目标 URL并按页面实际情况调整specific中的username_selector/password_selector/submit_selector支持id/name/css/xpath等写法在仓库根目录执行cd apps/terminal/applets/chrome python -c import base64,json;print(base64.b64encode(open(test_data_example.json,rb).read()).decode()) /tmp/data.b64 python main.py $(cat /tmp/data.b64)小应用将拉起 Chrome 打开资产页面并自动执行代填步骤可借此验证选择器表达式是否有效、iframe 切换与 sleep 时机是否合理再回到 JumpServer 平台侧完善资产/平台的代填配置。结语Chrome 小应用虽然文档极简但其源码完整覆盖了 Web 资产托管访问的关键工程问题Selenium 版本与驱动的严格匹配README 的核心约束、basic/script 两套代填策略、六种页面操作指令、安全模式下的标签页拦截扩展以及输入锁定、进度窗口、语言适配等体验细节。理解 app.py 与 common.py 的实现是排查该小应用连接失败与代填异常的最直接路径而 ChangeLog 则记录了它的每一次演进可作为版本升级时的回归检查清单。【免费下载链接】jumpserverJumpServer is an open-source Privileged Access Management (PAM) platform that provides DevOps and IT teams with on-demand and secure access to SSH, RDP, Kubernetes, Database and RemoteApp endpoints through a web browser.项目地址: https://gitcode.com/GitHub_Trending/ju/jumpserver创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表