Bitwarden 贡献文档
⮐ Bitwarden Contributing Documentation我的博客联系我
  • 关于
  • 入门
    • 概述
    • 工具
    • 服务器
      • 设置指南
      • 高级服务器设置
      • 数据库
        • MSSQL
        • 实体框架
      • 事件日志
      • Ingress 隧道
      • SCIM
      • 自托管指南
      • 系统管理门户
      • 单点登录 (SSO)
        • 本地 IdP
        • Okta
      • 故障排除
      • 用户机密
      • 公共 API
    • 网页客户端
      • 网页密码库
        • WebAuthn
      • 浏览器端
        • 生物识别解锁
        • Firefox 隐私模式
      • 桌面端
        • Mac App Store Dev
        • Microsoft Store
        • Native Messaging Test Runner
        • 更新测试
      • CLI
      • 故障排除
    • 移动端
      • Android
        • F-Droid
      • iOS
      • .NET MAUI (legacy)
        • Android
        • iOS
        • watchOS
    • SDK
      • 内部 SDK
      • Secrets Manager
        • Integrations
          • Kubernetes
    • 业务 App
      • 目录连接器
        • JumpCloud
        • OpenLDAP Docker 服务器
      • Key Connector
      • Splunk App
  • 贡献
    • 贡献
    • 代码样式
      • =Android & Kotlin
      • Angular & TypeScript
      • C#
      • =Rust
      • T-SQL
      • =Swift
      • Tailwind
    • 数据库迁移
      • 进化数据库设计
    • 提交签名
    • 拉取请求
      • =贡献审查程序
      • 分支
      • 代码审查
      • UI 审查 - Chromatic
    • 无障碍
    • 依赖管理
    • 功能标记
    • 模板存储库
    • 测试
      • =数据库集成测试
      • 负载测试
      • 单元测试
        • 命名约定
        • 测试结构
    • 修改用户机密
  • 架构
    • 架构
    • 架构决策记录 (ADR)
      • 0001 - Angular Reactive Forms
      • 0002 - Public API for modules
      • 0003 - Adopt Observable Data Services for Angular
      • 0004 - Refactor State Service
      • 0005 - Refactor Api Service
      • 0006 - Clients: Use Jest Mocks
      • 0007 - Manifest V3 sync Observables
      • 0008 - Server: Adopt CQRS
      • 0009 - Composition over inheritance
      • 0010 - Angular Modules
      • 0011 - Scalable Angular Clients folder structure
      • 0012 - Angular Filename convention
      • 0013 - Avoid layered folder structure for request/response models
      • 0014 - Adopt Typescript Strict flag
      • 0015 - Short Lived Browser Services
      • 0016 - Move Decryption and Encryption to Views
      • 0017 - Use Swift to build watchOS app
      • 0018 - Feature management
      • 0019 - Adoption of Web Push
      • 0020 - Observability with OpenTelemetry
      • 0021 - Logging to Standard Output
      • =0022 - Authorization
      • =0023 - Identifying Integrated Clients
    • 移动客户端架构
      • =Android
      • =iOS
        • =推送通知故障排除提示
      • =.NET MAUI (legacy)
        • =概述
        • watchOS
    • =SDK 架构
      • =数据模型
      • =依赖
      • Password Manager
        • Web
          • =互操作性
      • =Secrets Manager
      • =服务器绑定
      • =版本控制和破坏性更改
    • 网络客户端架构
      • 概述
      • 数据模型
      • 表示层
        • Angular
        • CLI
      • =依赖注入
      • 服务层
        • Vision
        • 实现
    • 服务器架构
    • 深度剖析
      • 身份验证
        • 双重身份验证
      • =授权
      • =浏览器自动填充
        • 收集页面详细信息
        • 生成并执行填充脚本
        • 表单提交检测
        • Shadow DOM
        • =内联自动填充菜单
      • Captcha
      • =只读数据库副本
      • 事件日志
      • =FIDO2 和通行密钥
        • =凭据
        • =操作
        • =命名惯例
        • =实现
          • =提供程序
            • =浏览器扩展
          • =依赖方
            • =用于解密的通行密钥
        • =术语表
      • 推送通知
        • 移动端推送通知
        • 其他客户端推送通知
      • =SSH 密钥和代理
        • =SSH 代理
      • =状态提供程序框架
        • =派生状态
    • =安全
      • =定义
      • =原则
        • =P01 - 锁定的密码库是安全的
        • =P02 - 半受损设备密码库的有限安全性
        • =P03 - 完全损坏的系统没有安全性
        • =P04 - 控制密码库数据的访问权限
        • =P05 - 将安全漏洞的影响降至最低
      • =要求
由 GitBook 提供支持
在本页
  • 整体架构
  • 与 iOS 集成
  • 在 iPhone 与 Watch 之间同步
  • 状态
  • 持久化和加密
  • 崩溃报告
  1. 架构
  2. 移动客户端架构
  3. =.NET MAUI (legacy)

watchOS

上一页=概述下一页=SDK 架构

最后更新于1个月前

对应的

整体架构

watchOS 应用程序的结构如下:

  • src/watchOS:特定于 watchOS 平台的所有代码

    • bitwarden:存根 iOS App,以便 watchOS App 在 XCode 上有一个配套 App

    • bitwarden WatchKit App:我们设置资产的主 Watch App

    • bitwarden WatchKit Extension:Watch App 的所有逻辑和表示逻辑都在这里

因此,几乎所有与 Watch App 相关的内容都将放在 WatchKit 扩展中,而 WatchKit App 中将只包含资产和一些配置。

然后,在扩展中,我们有一个分层的架构:

  • 状态(这是 iOS 状态的一个非常简化的版本)

  • 持久化(这里我们使用 CoreData 与数据库交互)

  • 服务(TOTP 生成、加密服务和业务逻辑)

  • 表示(对于具有 MVVM 模式的 UI 使用 SwiftUI)

与 iOS 集成

watchOS App 是使用 XCode 和 Swift 开发的,我们需要将其集成到 .NET MAUI iOS App 中。

<PropertyGroup>
    <WatchAppBuildPath Condition=" '$(Configuration)' == 'Debug' ">$(Home)/Library/Developer/Xcode/DerivedData/bitwarden-cbtqsueryycvflfzbsoteofskiyr/Build/Products</WatchAppBuildPath>
    <WatchAppBuildPath Condition=" '$(Configuration)' != 'Debug' ">$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\..'))/watchOS/bitwarden.xcarchive/Products/Applications/bitwarden.app/Watch</WatchAppBuildPath>
    <WatchAppBundle>Bitwarden.app</WatchAppBundle>
    <WatchAppConfiguration Condition=" '$(Platform)' == 'iPhoneSimulator' ">watchsimulator</WatchAppConfiguration>
    <WatchAppConfiguration Condition=" '$(Platform)' == 'iPhone' ">watchos</WatchAppConfiguration>
    <WatchAppBundleFullPath Condition=" '$(Configuration)' == 'Debug' ">$(WatchAppBuildPath)/$(Configuration)-$(WatchAppConfiguration)/$(WatchAppBundle)</WatchAppBundleFullPath>
    <WatchAppBundleFullPath Condition=" '$(Configuration)' != 'Debug' ">$(WatchAppBuildPath)/$(WatchAppBundle)</WatchAppBundleFullPath>
</PropertyGroup>

...

<ItemGroup Condition=" '$(Configuration)' == 'Debug' AND Exists('$(WatchAppBundleFullPath)') ">
    <_ResolvedWatchAppReferences Include="$(WatchAppBundleFullPath)" />
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)' != 'Debug' ">
    <_ResolvedWatchAppReferences Include="$(WatchAppBundleFullPath)" />
</ItemGroup>
<PropertyGroup Condition=" '$(_ResolvedWatchAppReferences)' != '' ">
    <CodesignExtraArgs>--deep</CodesignExtraArgs>
</PropertyGroup>
<Target Name="PrintWatchAppBundleStatus" BeforeTargets="Build">
    <Message Text="WatchAppBundleFullPath: '$(WatchAppBundleFullPath)' exists" Condition=" Exists('$(WatchAppBundleFullPath)') " />
    <Message Text="WatchAppBundleFullPath: '$(WatchAppBundleFullPath)' does NOT exist" Condition=" !Exists('$(WatchAppBundleFullPath)') " />
</Target>

因此,在 PropertyGroup 上,WatchAppBundleFullPath 会根据配置和平台以及 XCode watchOS App 构建的输出结果组装在一起。然后,根据 Watch App 是否存在和配置情况,在一些 ItemGroup 中加入 Watch App。任务 _ResolvedWatchAppReferences 负责查看由 XCode 构建的 Bitwarden.app,如果它找到 Watch App,就会将其捆绑到 Xamarin iOS App。最后,如果 Watch App 已捆绑,则会启用深度签名并打印构建路径。

正如我们在 csproj 中看到的那样,要将 watchOS App 捆绑到 iOS App 中,我们需要以正确的平台为目标。因此,如果要使用设备,可在 XCode 上以设备为目标构建 watchOS App,构建完成后可转到 VS4M 构建 iOS App(该 App 将捆绑 watchOS App)并在设备上运行。

在 iPhone 与 Watch 之间同步

因此,每一边都有一个 Watch Connectivity Manager,它是每个平台上的服务进行通信而使用的接口。

WatchDTO 是在同步中发送的对象,其中包含 Watch 的所有信息。

状态

接下来是 Watch App 在给定时间内可能处于的状态:

  • 有效:一切正常,用户可以通过 TOTP 查看密码库密码

  • 需要登录:用户需要使用 iPhone 登录

  • 需要设置:用户需要在他们的 iPhone 上设置一个启用了「Connect to Watch」功能的账户

  • 需要高级会员:当前账户不是高级会员

  • 需要 2FA 项目:当前账户没有设置任何 TOTP 密码

  • 同步:在更换账户以及同步新的密码库 TOTP 时显示

  • 需要设备所有者验证:用户需要设置 Apple Watch 通行代码才能使用此 App

持久化和加密

崩溃报告

在撰写本文档时,尚未为开发环境配置 plist,因此在非 DEBUG 配置中启用 Crashlytics。

有一个 Log 类用于记录应用程序中发生的错误,但它仅在 DEBUG 配置中启用。

为此,我们采用了 Xamarin.Forms GitHub 存储库中提供的,并根据我们的需要对 iOS.csproj 进行了修改:

为了在 iPhone 和 Watch App之间同步数据,需要使用 。

在同步通信中,主要使用 ,因为它总能提供最新发送的数据,而且是在后台发送,对方设备不一定需要在范围内(因此,它被缓存直到可以交付)。此外, 还用于向对方发出要快速执行某些操作的信号(例如从 Watch 触发同步)。

在 Watch 上, 用作密码的持久化。因此,为了加密其中的数据,在每个加密属性中都使用了一个值转换器:StringEncryptionTransformer。

在转换器中,将调用 CryptoService,最终使用 和 256 位 对数据进行加密。密钥会在第一次加密时生成/加载,并存储在设备钥匙串中。

在所有其他移动应用程序中, 被用作崩溃报告工具。但是,它不支持 watchOS(也不支持用于处理崩溃的内部库)。

因此,在 watchOS App 上使用 ,并启用了基本的崩溃报告功能(这里还没有处理错误日志记录)。为此,需要在 CI 中注入 GoogleService-Info.plist 文件。

官方页面地址
解决方案
Watch Connectivity Framework
updateApplicationContext
sendMessage
CoreData
AES.GCM
SymmetricKey
AppCenter
Firebase Crashlytics