macOS 开发 -- URL 访问权限持久化(基于 Sandbox)

好久不见,最近有在好好学习哈哈,

今天来分享下基于 Sandbox 的 URL 访问权限持久化的方案。

写这篇文章的起因是:

简单浏览了下 Tencent/lemon-cleaner 的部分源码,

发现他们用 Apple Script 调用 Finder 操作文件,

这样很好地避免了权限问题,但是研究一番发现,没那么简单….

Bookmark 大法

这是我自己项目里使用的方法,

好处在于文件操作很自然, 不会让用户觉得自己的数据可以被随便乱翻(事实也确实是这样的)

  1. 将 App Sandbox –> File Access 内的 User Selected File 改为 Read/Write

  2. 在项目的 entitlements 文件中添加这样一项 com.apple.security.files.bookmarks.app-scope,设为 YES

  3. 使用 NSOpenPannel / NSSavePannel 选择需要访问的文件(夹)

在 SwiftUI 中直接用 .fileImporter 之类的 modifer 就行

这样就拿到了用户选择的 URL 啦,因为是用户选择的,目前这个 URL 是有权访问的

注意,是目前,重启 app 就不行了

因此我们需要把权限持久化。

  1. 保存 URL 的 bookmark
1
@AppStorage("bookmark") private var bookmark: Data?
1
2
3
4
5
do {
bookmark = try url.bookmarkData(options: .withSecurityScope)
} catch {
print(error.localizedDescription)
}
  1. (app 重启后)再次访问此 URL
1
2
3
4
5
6
7
guard let bookmark else { return }
var isStale = false
let url = try URL(resolvingBookmarkData: bookmark, options: .withSecurityScope, relativeTo: nil, bookmarkDataIsStale: &isStale)
url.startAccessingSecurityScopedResource()
// Do some file-related works like move, duplicate, etc.
// try? FileManager.default.moveItem(at: a, to: b)
url.stopAccessingSecurityScopedResource()

start 和 stop 一定要成对!!

这里属于是访问系统敏感数据,如果不及时 stop 的话系统可能会对 app 的权限做限制,

因此不能滥用,这就是 Sandbox 为什么安全、让人放心的原因了。

url.startAccessingSecurityScopedResource() 也会返回一个布尔值,告诉你你是否真的可以这里的数据了,如果为 true 才能算成功。

Apple Script 大法

Apple Script 实际上是代替用户操作的一种脚本,本质上是代替了手动的操作而已,因此这里可以操作所有文件了,在沙盒环境下当然是不会默认允许的。

如果启用了 Hardened Runtime,要先在里面启用 Apple Events,否则无法弹出请求框。

非 Sandbox

如果在 非 Sandbox 环境下,只需要配置 Privacy - AppleEvents Sending Usage Description 告诉用户你执行的脚本的功能是干啥的就行。

然后就可以任意调用 applications了,例如,调用 Finder 来 move 文件之类的。

别慌!即使是非 Sandbox 也会有一步“自动化”授权的!

Sandbox

在 Sandbox 环境下就会有限制了,不会让你能直接访问所有的 applications ,因为这可能会有潜在的恶意行为。

  1. 你还是得配置 Privacy - AppleEvents Sending Usage Description 告诉用户你执行的脚本的功能是干啥的,

  2. 你在需要使用对应的 applications 之前需要去 entitlements 里提前声明。(用到几个写几个)

1
2
3
4
<key>com.apple.security.temporary-exception.apple-events</key>
<array>
<string>com.apple.Finder</string>
</array>

这样你就可以在 app 中使用 NSAppleScript 执行脚本了。

否则,会报错 -600

因为是模拟用户操作的脚本,因此在移动文件、删除文件的时候都会有系统提示音哦~

结尾

目前我的项目中还是使用了 Bookmark 大法,更加简单,不会让用户觉得危险。

主要是 Apple Script 那些弹窗就蛮吓人了…

macOS 开发 -- URL 访问权限持久化(基于 Sandbox)

https://liyanan2004.github.io/sandbox-url-persistence/

作者

LiYanan

发布于

2022-11-08

更新于

2022-11-08

许可协议

评论