尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

OpenHuman 凭据管理模块深入解析:app-session 会话生命周期与 auth-profiles 加密存储

OpenHuman 凭据管理模块深入解析:app-session 会话生命周期与 auth-profiles 加密存储 OpenHuman 凭据管理模块深入解析app-session 会话生命周期与 auth-profiles 加密存储【免费下载链接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.项目地址: https://gitcode.com/GitHub_Trending/op/openhumancredentials是 OpenHuman 的凭据与认证中枢统一管理三件事应用会话app-sessionJWT 的登录/登出生命周期、各 Provider如 API Key、OAuth Token 集的磁盘凭据档案auth-profiles以及后端 OAuth 连接/交接与 Composio 直连模式BYO Key凭据槽。本文以 src/openhuman/security/credentials/README.md 为骨架结合模块源码逐层拆解其数据结构、加密持久化机制、RPC/CLI 接口与事件驱动拆解流程帮助读者掌握该模块的完整工作原理与排查要点。模块定位与职责边界该模块源码位于 src/openhuman/security/credentials/对外只暴露auth.*JSON-RPC / CLI 命名空间所有能力都经由AuthService门面与AuthProfilesStore持久化引擎落地。其核心职责可概括为以下七个方面会话 JWT 管理存储并校验app-sessionProviderdefault档案的会话令牌包括本地离线会话与后端GET /auth/me校验。登录编排激活用户级 OpenHuman 目录、首次激活时清理登录前匿名会话线程、绑定记忆/会话持久化、引导 subconscious并启动登录门控服务本地 AI、语音、听写、自动补全。登出/会话过期拆解移除 JWT、清除活跃用户标记、停止登录门控服务、重置 subconscious并翻转调度器scheduler-gate的 signed-out 覆盖位。Provider 凭据档案以命名档案named auth profiles形式持久化任意 Provider 的凭据token 元数据字段支持列出、删除、设置活跃档案以及按前缀列出分组命名空间如channel:*。后端 OAuth 流程连接 URL 生成、集成列表、交接令牌handoff token获取、一次性客户端密钥获取、集成吊销。Composio 直连模式存取/清除 Composio 直连 API Keycomposio-directProvider。通用加解密通过SecretStore加密/解密任意机密。核心文件地图文件职责mod.rs模块出口。重导出core::*、ops同时以rpc别名导出、Composio-direct 辅助函数、schema 控制器all_credentials_controller_schemas/all_credentials_registered_controllers及crate::api::rest的后端 OAuth REST 类型。core.rsAuthService门面封装AuthProfilesStore——store/get/remove/set-active 档案、解析 Bearer Token、profile-id 选择逻辑override → active → default → 同 Provider 任意档案、Provider 规范化、state 目录推导。profiles.rs持久化引擎。定义AuthProfile/TokenSet/AuthProfileKind/AuthProfilesData与AuthProfilesStore——原子 JSON 读写、keychain 与加密 JSON 双轨密钥处理、旧版密文迁移、损坏档案隔离、PID 感知的陈旧锁恢复。ops.rs拆分为 ops_part_01.rs、ops_part_02.rs业务逻辑 RPC 入口返回RpcOutcomeT。会话生命周期、登录/登出服务编排、Provider 凭据 CRUD、OAuth 流程、Composio-direct 密钥辅助、机密加解密。以rpc别名重导出。schemas.rsauth.*控制器 schema 与handle_*分发器委托给ops。定义all_controller_schemas/all_registered_controllers。session_support.rs会话/认证辅助build_session_state、get_session_token、load_app_session_profile、summarize_auth_profile、本地会话检测/slug、字段解析。RPC 与 HTTP host 共用。responses.rs响应 DTOAuthStateResponse、AuthProfileSummary。cli.rsCLI 认证入口cli_auth_login/logout/status/list按app-session与 Provider 分流解析--field keyvalue。bus.rsSessionExpiredSubscriber——DomainEvent::SessionExpired的EventHandler执行规范化的会话拆解。配套测试以#[path ...]方式内嵌在 ops_tests.rs、profiles_tests.rs、schemas_tests.rs 中同时core.rs、session_support.rs、bus.rs、cli.rs内均有#[cfg(test)]内联测试。数据结构与公共 API核心类型AuthServicecore.rs唯一的对外门面方法包括from_config、new、load_profiles、store_provider_token、set_active_profile、remove_profile、get_profile、get_provider_bearer_token。AuthProfileprofiles.rs单个凭据档案字段为idprovider:profile_name拼接、provider、profile_name、kindOAuth/Token、account_id、workspace_id、token_setOAuth 令牌集、tokenToken 类令牌、metadata有序BTreeMap、created_at/updated_at。TokenSetOAuth 令牌集含access_token、refresh_token、id_token、expires_at、token_type、scope并提供is_expiring_within(skew)预判过期。AuthProfileKind序列化为 kebab-case 的oauth/token两种类型由parse_profile_kind严格解析未知值直接报错丢弃。AuthProfilesData磁盘数据整体含schema_version当前为 1、updated_at、active_profilesprovider → profile-id、profilesid → profile。AuthProfilesStore持久化引擎见下一节。关键常量APP_SESSION_PROVIDER app-session、DEFAULT_AUTH_PROFILE_NAME defaultcore.rsCOMPOSIO_DIRECT_PROVIDER composio-direct定义于 opsLOCAL_SESSION_USER_ID localsession_support.rsSESSION_EXPIRES_AT_META session_expires_at会话档案元数据中记录的 JWTexpRFC3339 键、SESSION_EXPIRY_SKEW_SECS 30提前 30 秒判定过期档案选择与 Provider 规范化normalize_provider会将 Provider 名 trim 并转为小写空字符串直接报错。select_profile_idcore.rs的解析优先级严格为显式 override → active 档案 →default档案 → 该 Provider 的任意档案。resolve_requested_profile_id支持两种写法包含:的字符串视为完整档案 id如channel:telegram否则按provider:name拼接。磁盘持久化auth-profiles.json 与密钥处理AuthProfilesStore将凭据写入配置 state 目录config.config_path的父目录登录后切换为用户级目录下的auth-profiles.json文件名常量见 profiles.rs。整体布局为schema_version当前 1、updated_at、active_profilesprovider → profile-id、profilesid → profile。双轨密钥存储机密字段token / access_token / refresh_token / id_token的落盘方式按运行环境自动切换OS 系统钥匙串keychain优先当crate::openhuman::security::keyring::is_available可用时所有 token 字段以单个 keychain 条目存储key 格式为{user_id}:auth:{profile_id}其中user_id从 state 目录推导典型路径~/.openhuman/users/uid-123取末段为uid-123异常布局则退化为路径的 FNV-1a 哈希path-{hex}见 profiles.rs。此时 JSON 中不含任何机密字段。加密 JSON 回退在无头/CI 等无钥匙串环境下token 字段经SecretStore用ChaCha20-Poly1305加密后写入 JSON。文件权限与原子写加密 JSON 是 Linux 及无钥匙串安装的常态为防他人同机可读写入走write_owner_onlyprofiles.rsUnix 下以0o600模式创建文件并显式set_permissions避免fs::write默认的0644权限写临时文件后经 rename 原子替换。写与 rename 两个阶段各有 6 次重试预算PERSIST_RETRY_ATTEMPTS 6、退避基址 100ms整体约 6.2s 最坏耗时仍远小于锁超时。崩溃安全与锁文件所有变更由auth-profiles.lock守卫该锁文件带有 PID 标记三层回收机制防卡死进程内注册表in_process_lock_for按规范化路径为每个锁文件维护一个static Mutex别名路径相对/绝对、符号链接、Windows 大小写变体共享同一把进程内锁避免同进程第二个获取者把活锁误判为泄漏。跨进程陈旧锁回收STALE_LOCK_AGE_MS 30_000超过即视为泄漏、无 PID 的畸形锁MALFORMED_LOCK_GRACE_MS 2_000快速回收、LOCK_TIMEOUT_MS 35_000兜底。锁的释放Drop中带 5 次重试卸载应对 Windows AV/索引器短暂占用句柄失败则交由自持锁回收与年龄回收兜底——这是修复杀死进程后重开卡在 Initializing OpenHuman 约 30 秒的关键机制。磁盘满StorageFull/ReadOnlyFilesystem导致锁创建失败时读路径可以安全跳过排他锁写方本就原子发布其余错误照常上抛保持可见。迁移、隔离与自我修复加载时会迁移旧版enc:/enc2:密文字段并将机密提升promote进系统钥匙串。无法解密或kind非法的单个档案会被丢弃而非毒化整个存储。无法解析的整体文件会被隔离quarantine重命名为auth-profiles.corrupt-ts.json并重置为空存储保证应用可继续启动。app-session 会话生命周期会话令牌作为app-sessionProvider 的default档案存储。注意 README 的明确警告store_session远不止存一个 token——它同时负责目录激活、线程清理、服务启动是整个登录漏斗而非薄 setter。登录编排登录时依次执行激活用户级 OpenHuman 目录user_openhuman_dir/write_active_user_id等、首次激活清除登录前匿名会话线程、绑定记忆与会话持久化、引导 subconscious、启动登录门控服务。存储时会用GET /auth/me校验后端用户档案带user_id_from_auth_me_payload解析并记录session_expires_at元数据。校验有独立预算默认 12s可通过环境变量OPENHUMAN_AUTH_ME_STORE_TIMEOUT_MS覆盖对 408/429/500/502/503/504/520 等瞬态状态做 150ms 间隔重试避免慢后端拖垮桌面端登录 RPC 的前端超时预算对应 SentryTAURI-REACT-1V的修复。嵌入宿主libraryHarness环境下则完全绕开全局~/.openhuman/active_user.toml状态全部限定在自身Config路径下。本地离线会话本地会话完全由 JWT 签名段字面量为local判定is_local_session_tokensession_support.rs恰好四段且第三段为local。此类会话跳过后端校验、永远不会被判定为过期用户 id 为local-{hostname-slug}主机名小写化并 slug 化见local_session_user_id。会话过期检测与 401 拦截require_live_session_tokensession_support.rs是每个后端authed_json调用的标准闸门三种结果无令牌 →no backend session token错误本地离线不联网。令牌记录的exp已过含 30 秒提前量→在发起注定 401 的请求之前发布一次SessionExpired事件经调度器门去重N 个并行调用只发一条并返回SESSION_EXPIRED哨兵错误。无exp记录的令牌本地离线 / 无 exp JWT→ 仅做存在性检查服务器端吊销仍由统一的 401 扁平化网络兜底。该机制是 TAURI-RUST-8WY / 8WZ/teams/me/usage、/payments/stripe/currentPlan的 401 洪泛的根因修复把 401 在源头掐断而不是事后降级。登出与拆解clear_session移除 JWT、清除活跃用户标记、停止登录门控服务语音服务器、本地 AI 复位为 idle 但不杀掉 Ollama 进程——它可能服务其他客户端或正在下载模型、重置 subconscious并翻转调度器 signed-out 覆盖位。登录门控服务编排start_login_gated_services/stop_login_gated_servicesops_part_01.rs并发启动相互独立的服务唯一顺序约束是语音服务器必须先于独立听写监听器二者争抢 macOS 上唯一的 rdev 全局监听器本地 AIOllama、embeddings——最重的预热项被移出关键路径语音热键voice server 按需独立听写监听always-on 持续监听连续麦克风 VAD → STT → Agent其 Windows WASAPI 冷启动为阻塞型就绪握手。此前串行启动使冷启动耗时叠加本地 AI 引导 Windows 麦克风初始化叠加出约 10 秒的卡顿热键/命令注册还被挤到 Ollama 预热之后#3490 改为并行后就绪时间由最慢单服务决定而非总和。单元测试下默认跳过真实后台服务cfg!(test)编译期移除需要时用OPENHUMAN_RUN_LOGIN_GATED_SERVICES_IN_TEST显式开启。auth.* RPC / CLI 接口命名空间authJSON-RPCopenhuman.auth_*/ CLIschema 定义于 schemas.rs方法说明auth_store_session存储并校验 app-session JWT。auth_clear_session移除已存的 app-session 凭据。auth_get_state当前认证/会话状态AuthStateResponse。auth_get_session_token读取已存的 app-session 令牌。auth_get_me获取当前已认证的后端用户档案。auth_consume_login_token消费一次性登录交接令牌 → 会话 JWT。auth_create_channel_link_token生成短时渠道链接令牌telegram/discord。auth_store_provider_credentials为某档案存储 Provider 凭据。auth_remove_provider_credentials移除 Provider 凭据。auth_list_provider_credentials列出已存 Provider 凭据可选 Provider 过滤。auth_oauth_connect为 Provider 创建 OAuth 连接 URL。auth_oauth_list_integrations列出当前会话的 OAuth 集成。auth_oauth_fetch_integration_tokens获取集成交接令牌。auth_oauth_fetch_client_key获取加密集成的一次性客户端密钥共享。auth_oauth_revoke_integration吊销 OAuth 集成。list_provider_credentials_by_prefix与 Composio-direct/secret 辅助函数是公开 ops 但未注册为auth.*控制器——由其他域直接调用。CLI 侧cli.rs 提供cli_auth_login/logout/status/list统一先load_config_with_timeout再按provider app-session分流到会话流或 Provider 凭据流。--field keyvalue由parse_field_equals_entries解析为 JSON 对象缺失、空 key 均报错支持以--profile指定档案名、--set-active控制是否置为活跃。SessionExpired 事件订阅SessionExpiredSubscriberbus.rsname() credentials::session_expired_handler域过滤[auth]订阅 src/core/events.rs 中的DomainEvent::SessionExpired发布方是各 401 检测点如jsonrpc.invoke_method、llm_provider.api_error等执行规范拆解先翻转调度器 signed-out 覆盖位——所有后台 worker 会在下一次wait_for_capacity()处停摆不再向必然 401 的后端发请求且拆解期间重入闸门的任务同样停摆再调用clear_session移除 JWT、清除活跃用户标记、停止登录门控服务。重复事件安全幂等。本地离线会话则撤销第一步的翻转并 no-op。该订阅者是 issueOPENHUMAN-TAURI-1T一名用户会话过期后由 cron 驱动的 LLM 调用产生了 5,414 条 Sentry 事件的修复——没有它401 只会被检测而不会被处置下一轮循环继续 401。bus.rs的注释同时说明若拆解时配置加载失败调度器门仍被钉在 signed-out会话 JWT 本周期不清理但至少后台工作不会恶化局面。后端 OAuth 连接与交接OAuth 相关类型从crate::api::rest重导出BackendOAuthClient、ConnectResponse、IntegrationSummary、IntegrationTokensHandoff、decrypt_handoff_blob、user_id_from_auth_me_payload、user_id_from_profile_payload。整体流程为auth_oauth_connect取得连接 URL → 用户完成授权 →auth_consume_login_token消费一次性交接令牌换会话 JWT →auth_oauth_fetch_integration_tokens取交接令牌集 → 需要时auth_oauth_fetch_client_key取一次性客户端密钥共享并decrypt_handoff_blob解密集成凭据 →auth_oauth_revoke_integration吊销。会话令牌通过crate::api::jwt读取后端地址由crate::api::config::effective_backend_api_url解析。Composio 直连模式BYO Keycomposio-directProvider 提供三个直接辅助函数store_composio_api_key、get_composio_api_key、clear_composio_api_key另有 RPC 包装rpc_store_composio_api_key。调用方composio/{client,ops}.rs通过credentials::rpc使用该槽位实现自带 API Key 的直连模式。依赖关系与消费方模块依赖README 的 Dependencies 一节configConfig、配置加载、用户目录激活、onboarding 状态、security::keyringSecretStore加解密 系统钥匙串、cron::scheduler_gate登录/登出/过期翻转 signed-out 覆盖、memory::conversations清理 pre-login 线程、绑定会话持久化、memory登录后绑定记忆客户端、subconscious登录后引导 / 用户切换重置、inference/voice/autocomplete登录门控服务、api::config/api::jwt/api::rest后端地址、令牌读取、OAuth 客户端、core控制器注册表 RPC 信封 事件总线。消费方众多src/core/{all,auth,jsonrpc}.rs控制器接线与认证闸门、src/api/jwt.rs、app_state/ops.rs会话快照、channels/*受管凭据、composio/*BYO Key、config/schema/*、embeddings/cloud.rs、encryption/ops.rs、http_host/auth.rs、inference/*Provider 认证、OpenAI OAuth、migrations/unify_ai_provider_settings.rs、referral/ops.rs、subconscious/engine.rs与webhooks。注意事项与易踩坑点rpc.rs例外mod.rs同时以ops::*与pub use ops as rpc导出调用方统一走credentials::rpc::*这是文档化的rpc.rs 等价物例外——不存在独立的rpc.rs文件。历史路径引用responses.rs/session_support.rs注释中引用的crate::core_server是历史路径实际传输层 crate 是src/core/。store_session是登录漏斗做了目录激活、线程清理、服务启动等重编排不要当薄 setter 使用。本地会话判定只看 JWT 签名段是否字面量为local跳过后端校验且永不判过期。密钥永不落日志调试日志只记录长度/标记遵守 CLAUDE.md 的脱敏规则AuthProfileSummary也刻意只暴露metadata_keys排序后的键名、has_token/has_token_set布尔位而非任何令牌明文。GET /auth/me校验预算存储时校验上限默认 12 秒慢后端会快速失败进入调用方授权的挂起会话路径对 live-exp JWT而不是把已认证用户弹回登录页。Agent 工具声明与源码现状README 声明该模块不拥有 Agent 工具tools.rs不存在但从当前源码目录结构看已存在 tools.rs 与 tools_tests.rs 文件可以推断 README 的该声明可能已滞后于代码演进具体以源码为准。小结OpenHuman 的credentials模块是典型的表面简单、内部严谨的认证基础设施对外只有一组auth.*RPC/CLI 接口对内则完成了双轨加密持久化系统钥匙串 ChaCha20-Poly1305 回退、PID 感知的崩溃安全锁、损坏自愈、会话过期事件驱动的全链路拆解。理解它的档案选择优先级、本地会话判定与调度器闸门联动是排查登录异常、401 洪泛与卡在 Initializing OpenHuman等问题的关键前提。【免费下载链接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.项目地址: https://gitcode.com/GitHub_Trending/op/openhuman创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表