沙盒 Xamarin.Mac 应用

本文介绍用于在 App Store 上发布的 Xamarin.Mac 应用程序的沙盒。 它涵盖所有进入沙盒的元素,例如容器目录、权利、用户确定的权限、特权分离和内核强制实施。

概述

在 Xamarin.Mac 应用程序中使用 C# 和 .NET 时,可以使用与使用 Objective-C 或 Swift 时相同的沙盒化应用程序。

An example of the running app

在本文中,我们将介绍在 Xamarin.Mac 应用程序中处理沙盒的基本知识,以及进入沙盒的所有元素:容器目录、权利、用户确定的权限、特权分离和内核强制实施。 强烈建议先浏览 Hello、Mac 文章,特别是 Xcode 和 Interface Builder 和输出口和 操作 简介部分,因为它介绍本文中将要使用的关键概念和技术。

你可能还需要查看 Xamarin.Mac Internals 文档的“公开 C# 类/方法Objective-C”部分,其中还介绍了ExportRegister用于将 C# 类与Objective-C对象和 UI 元素连接起来的特性。

关于应用沙盒

应用沙盒通过限制应用程序对系统资源的访问权限,提供强大的防御,防止恶意应用程序在 Mac 上运行造成的损害。

非沙盒应用程序具有运行应用的用户的完整权限,并且可以访问或执行用户可以执行的任何操作。 如果应用包含安全漏洞(或其使用的任何框架),黑客可能会利用这些弱点,并使用该应用控制正在运行的 Mac。

通过限制对每个应用程序的资源的访问,沙盒应用提供了一道防线,防止在用户计算机上运行的应用程序发生盗窃、损坏或恶意意图。

应用沙盒是内置在 macOS(在内核级别强制执行)的访问控制技术,提供两倍的策略:

  1. 应用沙盒使开发人员能够描述 应用程序如何 与 OS 交互,这样,它只被授予完成作业所需的访问权限,并且不再授予访问权限。
  2. 应用沙盒允许用户通过“打开和保存”对话框无缝地授予对系统的进一步访问权限,拖放操作和其他常见的用户交互。

准备实现应用沙盒

本文中将详细讨论的应用沙盒的元素如下所示:

  • 容器目录
  • 权利
  • 用户确定的权限
  • 特权分离
  • 内核强制实施

了解这些详细信息后,你将能够创建一个计划,以便在 Xamarin.Mac 应用程序中采用应用沙盒。

首先,需要确定应用程序是否适合沙盒(大多数应用程序)。 接下来,需要解决任何 API 不兼容问题,并确定需要的应用沙盒的哪些元素。 最后,了解如何使用特权分离来最大程度地提高应用程序的防御级别。

采用应用沙盒时,应用程序使用的某些文件系统位置将有所不同。 具体而言,应用程序将具有容器目录,该目录将用于应用程序支持文件、数据库、缓存和不是用户文档的任何其他文件。 macOS 和 Xcode 都支持将这些类型的文件从其旧位置迁移到容器。

沙盒快速入门

在本部分中,我们将创建一个简单的 Xamarin.Mac 应用,该应用使用 Web 视图(这要求在沙盒下受到限制的网络连接,除非特别请求)作为应用沙盒入门的示例。

我们将验证应用程序是否实际上是沙盒的,并了解如何排查和解决常见的应用沙盒错误。

创建 Xamarin.Mac 项目

让我们执行以下操作来创建示例项目:

  1. 启动 Visual Studio for Mac,然后单击“ 新建解决方案”。 链接。

  2. 从“新建项目”对话框中,选择“Mac>应用 Cocoa 应用”>

    Creating a new Cocoa App

  3. 单击“ 下一步 ”按钮,输入 MacSandbox 项目名称,然后单击“ 创建 ”按钮:

    Entering the app name

  4. 在 Solution Pad,双击 Main.storyboard 文件将其打开,以便在 Xcode 中编辑:

    Editing the main storyboard

  5. Web 视图 拖到窗口上,调整其大小以填充内容区域,并将其设置为随窗口一起增长和收缩:

    Adding a web view

  6. 为名为 webView 的 Web 视图创建一个出口:

    Creating a new outlet

  7. 返回到 Visual Studio for Mac,然后双击 Solution Pad 中的ViewController.cs文件将其打开以供编辑。

  8. 添加以下 using 语句: using WebKit;

  9. ViewDidLoad使方法如下所示:

    public override void AwakeFromNib ()
    {
        base.AwakeFromNib ();
        webView.MainFrame.LoadRequest(new NSUrlRequest(new NSUrl("http://www.apple.com")));
    }
    
  10. 保存所做更改。

运行应用程序并确保 Apple 网站显示在窗口中,如下所示:

Showing an example app run

对应用进行签名和预配

在启用应用沙盒之前,首先需要预配和签名 Xamarin.Mac 应用程序。

让我们执行以下操作:

  1. 登录到 Apple 开发人员门户:

    Logging into the Apple Developer Portal

  2. 选择 证书、标识符和配置文件

    Selecting Certificates, Identifiers & Profiles

  3. 在 Mac 应用,选择标识符”

    Selecting Identifiers

  4. 为应用程序创建新 ID:

    Creating a new App ID

  5. 在“预配配置文件”下,选择“开发

    Selecting Development

  6. 创建新的配置文件并选择 Mac 应用开发

    Creating a new profile

  7. 选择上面创建的应用 ID:

    Selecting the App ID

  8. 选择此配置文件的开发人员:

    Adding developers

  9. 选择此配置文件的计算机:

    Selecting the allowed computers

  10. 为配置文件指定名称:

    Giving the profile a name

  11. 单击“完成”按钮。

重要

在某些情况下,可能需要直接从 Apple 开发人员门户下载新的预配配置文件,然后双击它进行安装。 你可能还需要停止并重启 Visual Studio for Mac,然后才能访问新配置文件。

接下来,我们需要在开发计算机上加载新的应用 ID 和配置文件。 让我们执行以下操作:

  1. 启动 Xcode 并从 Xcode 菜单中选择首选项

    Editing accounts in Xcode

  2. 单击“查看详细信息...”按钮:

    Clicking the View Details button

  3. 单击“刷新”按钮(左下角)。

  4. 单击“完成”按钮。

接下来,我们需要在 Xamarin.Mac 项目中选择新的应用 ID 和预配配置文件。 让我们执行以下操作:

  1. 在 Solution Pad,双击 Info.plist 文件将其打开以供编辑。

  2. 确保 捆绑标识符 与上面创建的应用 ID 匹配(示例: com.appracatappra.MacSandbox):

    Editing the Bundle Identifier

  3. 接下来,双击 Entitlements.plist 文件并确保 iCloud 密钥值存储和iCloud 容器都与上面创建的应用 ID 匹配(例如: com.appracatappra.MacSandbox

    Editing the Entitlements.plist file

  4. 保存所做更改。

  5. 在 Solution Pad,双击项目文件以打开其选项进行编辑:

    Editign the solution's options

  6. 选择“Mac 签名”,然后检查对应用程序捆绑包进行签名,然后对安装程序包进行签名。 在“预配配置文件”下 ,选择上面创建的配置文件

    Setting the provisioning profile

  7. 单击“完成”按钮。

重要

可能需要退出并重启 Visual Studio for Mac 才能识别 Xcode 安装的新应用 ID 和预配配置文件。

排查预配问题

此时,应尝试运行应用程序,并确保所有内容都已正确签名和预配。 如果应用仍然像以前一样运行,则一切正常。 如果发生故障,可能会收到如下所示的对话框:

An example provisioning issue dialog

下面是预配和签名问题的最常见原因:

  • 应用捆绑 ID 与所选配置文件的应用 ID 不匹配。
  • 开发人员 ID 与所选配置文件的开发人员 ID 不匹配。
  • 要测试的 Mac 的 UUID 未注册为所选配置文件的一部分。

如果出现问题,请在 Apple 开发人员门户中更正问题,在 Xcode 中刷新配置文件并在 Visual Studio for Mac 中执行干净生成。

启用应用沙盒

通过在项目选项中选择检查框来启用应用沙盒。 请执行以下操作:

  1. 在 Solution Pad,双击 Entitlements.plist 文件将其打开以供编辑。

  2. 检查“启用权利”和“启用应用沙盒”:

    Editing entitlements and enabling sandboxing

  3. 保存所做更改。

此时,你已启用应用沙盒,但尚未提供 Web 视图所需的网络访问权限。 如果现在运行应用程序,应会看到一个空白窗口:

Showing the web access being blocked

验证应用是否已沙盒化

除了资源阻止行为之外,还有三种主要方法可以判断 Xamarin.Mac 应用程序是否已成功沙盒化:

  1. 在 Finder 中,检查文件夹的内容 ~/Library/Containers/ - 如果应用已沙盒化,则会有一个名为“捆绑标识符”的文件夹(例如: com.appracatappra.MacSandbox

    Opening the app's bundle

  2. 系统将应用视为活动监视器中的沙盒:

    • 启动活动监视器(在下方 /Applications/Utilities)。
    • 选择“查看>”并确保沙盒菜单项检查。
    • 确保为应用程序读取 Yes 沙盒列:

    Checking the app in the Activity Monitor

  3. 检查应用二进制文件是否已沙盒化:

    • 启动终端应用。
    • 导航到应用程序 bin 目录。
    • 发出此命令: codesign -dvvv --entitlements :- executable_path (应用程序的路径在哪里 executable_path ):

    Checking the app on the command line

调试沙盒应用

调试器通过 TCP 连接到 Xamarin.Mac 应用,这意味着在启用沙盒时,它无法连接到应用,因此,如果尝试在没有启用适当权限的情况下运行应用,则会收到错误“无法连接到调试器”。

Setting the required options

允许传出网络连接(客户端)权限是调试器所需的权限,启用此权限将允许正常调试。 由于你不能在没有调试的情况下进行调试,因此我们已更新 CompileEntitlements 了目标,以便 msbuild 自动将该权限添加到仅针对调试生成沙盒的任何应用的权利。 发布版本应使用权利文件中指定的权利(未修改)。

解决应用沙盒冲突

如果沙盒 Xamarin.Mac 应用程序尝试访问未显式允许的资源,则会发生应用沙盒冲突。 例如,我们的 Web 视图不再能够显示 Apple 网站。

当 Visual Studio for Mac 中指定的权利设置不符合应用程序要求时,将发生最常见的应用沙盒冲突源。 同样,回到我们的示例,缺少的网络连接权利,使 Web 视图不起作用。

发现应用沙盒冲突

如果怀疑 Xamarin.Mac 应用程序中发生了应用沙盒冲突,则发现问题的最快方法是使用 控制台 应用。

请执行以下操作:

  1. 编译有问题的应用,并从 Visual Studio for Mac 运行它。

  2. 打开 控制台 应用程序(发件人 /Applications/Utilties/)。

  3. 在边栏中选择 “所有邮件 ”,然后在搜索中输入 sandbox

    An example of a sandboxing issue in the console

对于上面的示例应用,可以看到 Kernal 由于应用沙盒而阻止 network-outbound 了流量,因为我们没有请求该权限。

使用权利修复应用沙盒冲突

现在,我们已经了解如何查找应用沙盒冲突,让我们看看如何通过调整应用程序的权利来解决这些冲突。

请执行以下操作:

  1. 在 Solution Pad,双击 Entitlements.plist 文件将其打开以供编辑。

  2. “权利”部分下,检查“允许传出网络”连接(客户端)检查框:

    Editing the entitlements

  3. 保存对应用程序的更改。

如果我们对示例应用执行上述操作,然后生成并运行它,则 Web 内容现在将显示为预期。

深入应用沙盒

应用沙盒提供的访问控制机制很少且易于理解。 但是,每个应用将采用应用沙盒的方式是唯一的,并基于应用的要求。

为保护 Xamarin.Mac 应用程序免受恶意代码的攻击,应用(或它使用的库或框架之一)中只需要一个漏洞,才能控制应用与系统的交互。

应用沙盒旨在通过允许你指定应用程序与系统的预期交互来防止接管(或限制它可能导致的损害)。 系统只会授予对应用程序完成其作业所需的资源的访问权限,且无需执行任何操作。

在针对应用沙盒进行设计时,你要针对最坏的情况进行设计。 如果应用程序确实受到恶意代码的入侵,则只能访问应用沙盒中的文件和资源。

权利和系统资源访问

如上所述,未沙盒的 Xamarin.Mac 应用程序被授予运行应用的用户的完全权限和访问权限。 如果受到恶意代码的入侵,则非受保护的应用可以充当恶意行为的代理,并有可能造成伤害。

通过启用应用沙盒,可以删除除一组最少的权限,然后使用 Xamarin.Mac 应用的权利按需重新启用这些权限。

通过编辑其 Entitlements.plist 文件并检查或从编辑器下拉列表中选择所需的权限来修改应用程序的应用沙盒资源:

Editing the entitlements

容器目录和文件系统访问

当 Xamarin.Mac 应用程序采用应用沙盒时,它有权访问以下位置:

  • 应用容器目录 - 首次运行时,OS 会创建一个特殊的 容器目录,其中所有资源都位于其中,只有该目录可以访问该目录 。 该应用将对此目录具有完全读/写访问权限。
  • 应用组容器目录 - 可以向应用授予对同一组中应用之间共享的一个或多个 组容器 的访问权限。
  • 用户指定的文件 - 应用程序会自动获取对用户显式打开或拖放到应用程序上的文件的访问权限。
  • 相关项 - 使用适当的权利,应用程序可以访问具有相同名称但扩展名不同的文件。 例如,已保存为 .txt 文件和文件 .pdf的文档。
  • 临时目录、命令行工具目录和特定的世界可读位置 - 你的应用对系统指定的其他定义位置中的文件具有不同程度的访问权限。

应用容器目录

Xamarin.Mac 应用程序的应用容器目录具有以下特征:

  • 它位于用户主目录(通常 ~Library/Containers)中的隐藏位置,可通过应用程序中的函数(如下所示)进行访问 NSHomeDirectory 。 由于它位于“主页”目录中,因此每个用户都将为应用获取自己的容器。
  • 应用对容器目录及其所有子目录及其内部文件具有无限制的读/写访问权限。
  • 大多数 macOS 的路径查找 API 都与应用的容器相关。 例如,容器将有自己的 (通过 NSLibraryDirectory)、 应用程序支持首选项 子目录进行访问。
  • macOS 通过代码签名建立并强制实施应用与其容器之间的连接。 即使是另一个应用也尝试使用其 捆绑标识符欺骗应用,但由于代码签名,它将无法访问容器。
  • 容器不适用于用户生成的文件。 而是适用于应用程序使用的文件,例如数据库、缓存或其他特定类型的数据。
  • 对于 鞋盒 类型的应用(如 Apple 的照片应用),用户的内容将进入容器。

重要

遗憾的是,Xamarin.Mac 还没有 100% 的 API 覆盖率(与 Xamarin.iOS 不同),因此 NSHomeDirectory API 尚未在当前版本的 Xamarin.Mac 中映射。

作为临时解决方法,可以使用以下代码:

[System.Runtime.InteropServices.DllImport("/System/Library/Frameworks/Foundation.framework/Foundation")]
public static extern IntPtr NSHomeDirectory();

public static string ContainerDirectory {
    get {
        return ((NSString)ObjCRuntime.Runtime.GetNSObject(NSHomeDirectory())).ToString ();
        }
}

应用组容器目录

从 Mac macOS 10.7.5(及更高)开始,应用程序可以使用 com.apple.security.application-groups 权利访问组中所有应用程序通用的共享容器。 可以将此共享容器用于面向非用户的内容,例如数据库或其他类型的支持文件(如缓存)。

组容器会自动添加到每个应用的沙盒容器(如果它们是组的一部分),并存储在 ~/Library/Group Containers/<application-group-id>其中。 组 ID 必须 以开发团队 ID 和句点开头,例如:

<team-id>.com.company.<group-name>

有关详细信息,请参阅 Apple 在权利密钥参考向应用程序组添加应用程序。

应用容器外部的 Powerbox 和文件系统访问

沙盒 Xamarin.Mac 应用程序可以通过以下方式访问其容器外部的文件系统位置:

  • 在用户的特定方向(通过打开和保存对话框或其他方法(如拖放) 。
  • 通过使用特定文件系统位置(如 /bin 或) /usr/lib的权利。
  • 当文件系统位置位于世界可读(如共享)的某些目录中时。

Powerbox 是与用户交互以扩展沙盒 Xamarin.Mac 应用的文件访问权限的 macOS 安全技术。 Powerbox 没有 API,但在应用调用或NSOpenPanelNSSavePanel应用时以透明方式激活。 Powerbox 访问是通过为 Xamarin.Mac 应用程序设置的权利启用的。

当沙盒应用显示“打开”或“保存”对话框时,该窗口由 Powerbox(而不是 AppKit)显示,因此有权访问用户有权访问的任何文件或目录。

当用户从“打开”或“保存”对话框中选择文件或目录(或拖动到应用图标上)时,Powerbox 会将关联的路径添加到应用的沙盒。

此外,系统会自动将以下内容允许沙盒应用:

  • 连接系统输入法。
  • 从“服务”菜单中调用用户选择的服务(仅适用于服务提供商标记为沙盒应用安全的服务)。
  • 从“打开最近打开”菜单中选择“打开文件”。
  • 在其他应用程序之间使用复制和粘贴。
  • 从以下可读位置读取文件:
    • /bin
    • /sbin
    • /usr/bin
    • /usr/lib
    • /usr/sbin
    • /usr/share
    • /System
  • 读取和写入由 . NSTemporaryDirectory创建的目录中的文件。

默认情况下,沙盒 Xamarin.Mac 应用打开或保存的文件将保持可访问状态,直到应用终止(除非应用退出时文件仍处于打开状态)。 下次启动应用时,打开的文件将通过 macOS 恢复功能自动还原到应用的沙盒。

若要为位于 Xamarin.Mac 应用容器外部的文件提供持久性,请使用安全范围的书签(请参阅下文)。

应用沙盒允许应用访问具有相同文件名但不同扩展名的相关项。 此功能有两个部分:a) 应用 Info.plst 文件中相关扩展的列表,b) 代码告知沙盒应用将对这些文件执行的操作。

在以下两种情况下,这很有意义:

  1. 应用需要能够保存文件的不同版本(具有新的扩展名)。 例如,将 .txt 文件导出到 .pdf 文件。 若要处理这种情况,必须使用 a NSFileCoordinator 访问文件。 首先调用 WillMove(fromURL, toURL) 该方法,将文件移动到新的扩展名,然后调用 ItemMoved(fromURL, toURL)
  2. 该应用需要打开一个扩展名为一个的主文件,以及多个具有不同扩展名的支持文件。 例如,电影和字幕文件。 使用 a NSFilePresenter 获取对辅助文件的访问权限。 向属性提供主文件 PrimaryPresentedItemURL ,并将辅助文件提供给 PresentedItemURL 该属性。 打开主文件时,调用 AddFilePresenter 类的方法 NSFileCoordinator 注册辅助文件。

在这两种情况下,应用的 Info.plist 文件必须声明应用可以打开的文档类型。 对于任何文件类型,请将 NSIsRelatedItemType YES> 值添加到数组中的 CFBundleDocumentTypes 条目。

使用沙盒应用打开和保存对话框行为

从沙盒 Xamarin.Mac 应用调用这些限制时,将对其施加NSOpenPanelNSSavePanel以下限制:

  • 不能以编程方式调用 “确定 ”按钮。
  • 不能以编程方式更改用户的选择 NSOpenSavePanelDelegate

此外,以下继承修改已到位:

  • 非沙盒应用 - NSOpenPanelNSSavePanel``NSPanel``NSWindow``NSResponder``NSObject``NSOpenPanel``NSSavePanel``NSObject``NSOpenPanel``NSSavePanel

安全范围的书签和持久性资源访问

如上所述,沙盒 Xamarin.Mac 应用程序可以通过直接用户交互(由 PowerBox 提供)访问容器外部的文件或资源。 但是,在应用启动或系统重启时,对这些资源的访问不会自动保留。

通过使用 安全范围的书签,沙盒 Xamarin.Mac 应用程序可以保留用户意向,并在应用重启后保留对给定资源的访问权限。

安全范围的书签类型

使用安全范围的书签和持久资源访问时,有两个 sistine 用例:

  • 应用范围的书签提供对用户指定的文件或文件夹的持久访问。

    例如,如果沙盒 Xamarin.Mac 应用程序允许使用打开外部文档进行编辑(使用), NSOpenPanel应用可以创建应用范围的书签,以便将来再次访问同一文件。

  • 文档范围的书签提供对子文件的特定文档持久访问。

例如,一个视频编辑应用,用于创建一个项目文件,该文件有权访问单个图像、视频剪辑和声音文件,稍后将合并为单个电影。

当用户(通过 a) NSOpenPanel将资源文件导入项目时,应用会为项目中存储的项创建文档范围的书签,以便该文件始终可供应用访问。

任何可以打开书签数据和文档本身的应用程序都可以解析文档范围的书签。 这支持可移植性,允许用户将项目文件发送给其他用户,并让所有书签也适用于它们。

重要

文档范围的书签只能指向单个文件,而不能指向文件夹,并且该文件不能位于系统使用的位置(例如/private/Library)。

使用安全范围的书签

使用任一类型的安全作用域书签需要执行以下步骤:

  1. 在需要使用安全作用域书签的 Xamarin.Mac 应用中设置适当的权利 - 对于应用范围的书签 ,请将 com.apple.security.files.bookmarks.app-scope 权利密钥设置为 true。 对于文档范围的书签,请将 com.apple.security.files.bookmarks.document-scope 权利键设置为 true
  2. 创建安全范围的书签 - 为此,用户提供访问权限的任何文件或文件夹(例如,通过 NSOpenPanel ),应用将需要永久访问权限。 public virtual NSData CreateBookmarkData (NSUrlBookmarkCreationOptions options, string[] resourceValues, NSUrl relativeUrl, out NSError error)使用类的方法NSUrl创建书签。
  3. 解析安全作用域书签 - 当应用需要再次访问资源时(例如重启后),需要将书签解析为安全范围的 URL。 public static NSUrl FromBookmarkData (NSData data, NSUrlBookmarkResolutionOptions options, NSUrl relativeToUrl, out bool isStale, out NSError error)使用类的方法NSUrl解析书签。
  4. 显式通知系统要从安全作用域 URL 访问文件 - 在获取上述安全作用域 URL 后需要立即执行此步骤,或者以后在放弃对资源的访问权限后重新获得对资源的访问权限时,需要立即完成此步骤。 StartAccessingSecurityScopedResource ()调用类的方法NSUrl以开始访问安全范围的 URL。
  5. 显式通知系统你已完成从安全范围的 URL 访问文件 - 尽快,当应用不再需要访问该文件时,你应该通知系统(例如,如果用户关闭它)。 StopAccessingSecurityScopedResource ()调用类的方法NSUrl以停止访问安全范围的 URL。

放弃对资源的访问权限后,需要再次返回到步骤 4 以重新建立访问权限。 如果重启 Xamarin.Mac 应用,则必须返回到步骤 3 并重新解析书签。

重要

未能释放对安全范围的 URL 资源的访问权限将导致 Xamarin.Mac 应用泄漏内核资源。 因此,在重新启动文件系统位置之前,应用将无法再将其添加到其容器中。

应用沙盒和代码签名

启用应用沙盒并启用 Xamarin.Mac 应用(通过权利)的特定要求后,必须对项目进行代码签名,使沙盒生效。 必须执行代码签名,因为应用沙盒所需的权利链接到应用的签名。

macOS 强制应用容器与其代码签名之间的链接,这样任何其他应用程序都无法访问该容器,即使它欺骗了应用捆绑 ID 也是如此。 此机制的工作原理如下:

  1. 当系统创建应用的容器时,它会在该容器上设置访问控制列表(ACL)。 列表中的初始访问控制项包含应用的 指定要求(DR),该要求 描述了如何识别应用的未来版本(升级后)。
  2. 每次启动具有相同捆绑 ID 的应用时,系统都会检查应用的代码签名与容器 ACL 中某个条目中指定的指定要求匹配。 如果系统找不到匹配项,它将阻止应用启动。

代码签名的工作原理如下:

  1. 在创建 Xamarin.Mac 项目之前,请从 Apple 开发人员门户获取开发证书、分发证书和开发人员 ID 证书。
  2. 当 Mac App Store 分发 Xamarin.Mac 应用时,它使用 Apple 代码签名进行签名。

测试和调试时,将使用已签名的 Xamarin.Mac 应用程序版本(将用于创建应用容器)。 稍后,如果想要从 Apple App Store 测试或安装版本,它将使用 Apple 签名进行签名,并且无法启动(因为它没有与原始应用容器相同的代码签名)。 在这种情况下,你将获得类似于以下内容的崩溃报告:

Exception Type:  EXC_BAD_INSTRUCTION (SIGILL)

若要解决此问题,需要调整 ACL 入口以指向 Apple 签名版本的应用。

有关创建和下载沙盒所需的预配配置文件的详细信息,请参阅上面的“ 签名和预配应用 ”部分。

调整 ACL 条目

若要允许 Apple 签名版本的 Xamarin.Mac 应用运行,请执行以下操作:

  1. 打开终端应用(in /Applications/Utilities)。
  2. 打开 Xamarin.Mac 应用的 Apple 签名版本的 Finder 窗口。
  3. 在终端窗口中键入 asctl container acl add -file
  4. 从 Finder 窗口拖动 Xamarin.Mac 应用的图标,并将其拖放到终端窗口中。
  5. 文件的完整路径将添加到终端中的命令。
  6. Enter 执行该命令。

容器的 ACL 现在包含 Xamarin.Mac 应用和 macOS 这两个版本的指定代码要求,现在允许任一版本运行。

显示 ACL 代码要求的列表

可以通过执行以下操作来查看容器 ACL 中的代码要求列表:

  1. 打开终端应用(in /Applications/Utilities)。
  2. 键入 asctl container acl list -bundle <container-name>
  3. Enter 执行该命令。

通常是 <container-name> Xamarin.Mac 应用程序的捆绑标识符。

为应用沙盒设计 Xamarin.Mac 应用

为应用沙盒设计 Xamarin.Mac 应用时,应遵循一个常见的工作流。 也就是说,在应用中实现沙盒的具体细节对于给定应用的功能是独一无二的。

采用应用沙盒的六个步骤

为应用沙盒设计 Xamarin.Mac 应用通常包括以下步骤:

  1. 确定应用是否适合沙盒。
  2. 设计开发和分发策略。
  3. 解决任何 API 不兼容问题。
  4. 将所需的应用沙盒权利应用于 Xamarin.Mac 项目。
  5. 使用 XPC 添加特权分离。
  6. 实施迁移策略。

重要

你不仅必须在应用捆绑包中对主要可执行文件进行沙盒,而且必须沙盒包含每个帮助程序应用或该工具。 这是从 Mac App Store 分发的任何应用所必需的,如果可能,应针对任何其他形式的应用分发完成此操作。

有关 Xamarin.Mac 应用捆绑包中所有可执行二进制文件的列表,请在终端中键入以下命令:

find -H [Your-App-Bundle].app -print0 | xargs -0 file | grep "Mach-O .*executable"

应用程序的捆绑包的名称和路径在哪里 [Your-App-Bundle]

确定 Xamarin.Mac 应用是否适合沙盒

大多数 Xamarin.Mac 应用与应用沙盒完全兼容,因此适合沙盒。 如果应用需要应用沙盒不允许的行为,则应考虑一种替代方法。

如果应用需要以下行为之一,则它与应用沙盒不兼容:

  • 授权服务 - 使用应用沙盒时,不能使用 Authorization Services C 参考中所述的功能。
  • 辅助功能 API - 不能沙盒辅助应用,例如屏幕阅读器或控制其他应用程序的应用。
  • 将 Apple 事件发送到任意应用 - 如果应用需要将 Apple 事件发送到未知的任意应用,则无法将其沙盒化。 对于已知的已调用应用列表,该应用仍可以沙盒化,权利需要包含调用的应用列表。
  • 将分布式通知中的用户信息字典发送到其他任务 - 使用应用沙盒,在发布到NSDistributedNotificationCenter对象以传送其他任务时,不能包含userInfo字典。
  • 加载内核扩展 - 应用沙盒禁止加载内核扩展。
  • 应用沙盒禁止在“打开”和“保存”对话框中 模拟用户输入 - 以编程方式操作“打开”或“保存”对话框以模拟或更改用户输入。
  • 在其他应用 上访问或设置首选项 - 应用沙盒禁止操作其他应用的设置。
  • 配置网络设置 - 应用沙盒禁止操作网络设置。
  • 终止其他应用 - 应用沙盒禁止使用 NSRunningApplication 终止其他应用。

解决 API 不兼容问题

为应用沙盒设计 Xamarin.Mac 应用时,可能会遇到与某些 macOS API 的用法不兼容的情况。

下面是一些常见问题和可解决这些问题的事项:

  • 打开、保存和跟踪文档 - 如果使用其他 NSDocument任何技术管理文档,则应由于对应用沙盒的内置支持而切换到文档。 NSDocument 如果用户在 Finder 中移动文档,则自动使用 PowerBox,并支持将文档保留在沙盒中。
  • 保留对文件系统资源的 访问 - 如果 Xamarin.Mac 应用依赖于对其容器外部资源的持久访问,请使用安全范围的书签来维护访问权限。
  • 为应用创建登录项 - 使用应用 沙盒时,不能使用 LSSharedFileList 创建登录项,也不能使用 LSRegisterURL操作启动服务的状态。 SMLoginItemSetEnabled使用 Apples 使用 Service Management Framework 文档添加登录项中所述的函数。
  • 访问用户数据 - 如果使用 POSIX 函数(例如 getpwuid 从目录服务获取用户的主目录),请考虑使用 Cocoa 或 Core Foundation 符号,例如 NSHomeDirectory
  • 访问其他应用的 首选项 - 由于应用沙盒将查找路径 API 定向到应用的容器,因此修改首选项发生在该容器中,并且不允许访问其他应用首选项。
  • 在 Web 视图中 使用 HTML5 嵌入式视频 - 如果 Xamarin.Mac 应用使用 WebKit 播放嵌入式 HTML5 视频,则还必须将应用链接到 AV Foundation 框架。 应用沙盒将阻止 CoreMedia 播放这些视频,否则。

应用所需的应用沙盒权利

需要编辑要在应用沙盒中运行的任何 Xamarin.Mac 应用程序的权利,并检查“启用应用沙盒”检查框。

根据应用的功能,可能需要启用其他权利才能访问 OS 功能或资源。 将请求的权利降到运行应用所需的最低要求时,应用沙盒效果最佳,因此只需随机启用权利即可。

若要确定 Xamarin.Mac 应用所需的权利,请执行以下操作:

  1. 启用应用沙盒并运行 Xamarin.Mac 应用。
  2. 运行应用的功能。
  3. 打开控制台应用(可用/Applications/Utilities),并在“所有消息”日志中查找sandboxd冲突。
  4. 对于每个 sandboxd 冲突,请通过使用应用容器而不是其他文件系统位置来解决该问题,或者应用应用沙盒权利来启用对受限 OS 功能的访问权限。
  5. 重新运行并再次测试所有 Xamarin.Mac 应用功能。
  6. 重复,直到解决所有 sandboxd 冲突。

使用 XPC 添加特权分离

为应用沙盒开发 Xamarin.Mac 应用时,请查看应用在特权和访问权限方面的行为,然后考虑将高风险操作分成自己的 XPC 服务。

有关详细信息,请参阅 Apple 的“创建 XPC 服务和守护程序和服务编程指南”。

实施迁移策略

如果要发布以前未沙盒的 Xamarin.Mac 应用程序的新沙盒版本,则需要确保当前用户具有流畅的升级路径。

有关如何实现容器迁移清单的详细信息,请阅读 Apple 将 应用迁移到沙盒 文档。

总结

本文详细介绍了 Xamarin.Mac 应用程序的沙盒。 首先,我们创建了一个简单的 Xamarin.Mac 应用来显示应用沙盒的基础知识。 接下来,我们介绍了如何解决沙盒冲突。 然后,我们深入探讨了应用沙盒,最后,我们研究了为应用沙盒设计 Xamarin.Mac 应用。