该库定义了 Cryptomator for iOS 使用的云访问 API。
每个云存储服务都需要实现一次该 API。它也构成了应用各种 vault 格式的装饰层的基础,以便为云存储的 vault 提供明文视图。
您可以使用 Swift Package Manager。
.package(url: "https://github.com/cryptomator/cloud-access-swift.git", .upToNextMinor(from: "1.12.0"))
核心包包含几个协议、结构体和枚举,它们构成了该库的基础。异步调用使用 Promises 库实现。CloudProvider
是定义云访问的主要协议。
func fetchItemMetadata(at cloudPath: CloudPath) -> Promise<CloudItemMetadata>
func fetchItemList(forFolderAt cloudPath: CloudPath, withPageToken pageToken: String?) -> Promise<CloudItemList>
func downloadFile(from cloudPath: CloudPath, to localURL: URL, onTaskCreation: ((URLSessionDownloadTask?) -> Void)?) -> Promise<Void>
func uploadFile(from localURL: URL, to cloudPath: CloudPath, replaceExisting: Bool, onTaskCreation: ((URLSessionUploadTask?) -> Void)?) -> Promise<CloudItemMetadata>
func createFolder(at cloudPath: CloudPath) -> Promise<Void>
func deleteFile(at cloudPath: CloudPath) -> Promise<Void>
func deleteFolder(at cloudPath: CloudPath) -> Promise<Void>
func moveFile(from sourceCloudPath: CloudPath, to targetCloudPath: CloudPath) -> Promise<Void>
func moveFolder(from sourceCloudPath: CloudPath, to targetCloudPath: CloudPath) -> Promise<Void>
Vault 提供程序装饰云提供程序,并允许透明地访问基于 Cryptomator 加密方案的 vault。 它依赖于 cryptolib-swift 进行加密功能,并依赖于 GRDB 进行线程安全缓存。 有关 Cryptomator 加密方案的更多信息,请访问 docs.cryptomator.org 上的安全架构页面。
为了创建一个 vault 提供程序,您需要来自 cryptolib-swift 的一个 Masterkey
实例。 查看它的文档,了解如何创建一个主密钥。 并且自从 vault 格式 8 以来,您还需要一个 UnverifiedVaultConfig
实例。
let provider = ... // any other cloud provider
let vaultPath = ...
let masterkey = ...
let token = ...
let unverifiedVaultConfig = try UnverifiedVaultConfig(token: token)
let cryptoDecorator = try VaultProviderFactory.createVaultProvider(from: unverifiedVaultConfig, masterkey: masterkey, vaultPath: vaultPath, with: provider)
以及创建 vault 版本 6 或 7 的旧版 vault 提供程序
let provider = ... // any other cloud provider
let vaultVersion = ... // use `version` from the `MasterkeyFile` instance
let vaultPath = ...
let masterkey = ...
let cryptoDecorator = try VaultProviderFactory.createLegacyVaultProvider(from: masterkey, vaultVersion: vaultVersion, vaultPath: vaultPath, with: provider)
以下常量必须设置一次,例如,在您的 app delegate 中
let clientId = ... // your Box client identifier
let clientSecret = ... // your Box client secret
let sharedContainerIdentifier = ... // optional: only needed if you want to create a `BoxCloudProvider` with a background `URLSession` in an app extension
BoxSetup.constants = BoxSetup(clientId: clientId, clientSecret: clientSecret, sharedContainerIdentifier: sharedContainerIdentifier)
开始身份验证流程
let tokenStore = BoxTokenStore()
let credential = BoxCredential(tokenStore: tokenStore)
let viewController = ... // the presenting `UIViewController`
BoxAuthenticator.authenticate(credential: credential, from: viewController).then {
// authentication successful
}.catch { error in
// error handling
}
然后,您可以使用凭据创建一个 Box 提供程序
let provider = BoxCloudProvider(credential: credential)
或者使用后台 URLSession 创建一个 Box 提供程序
let sessionIdentifier = ...
let provider = BoxCloudProvider.withBackgroundSession(credential: credential, sessionIdentifier: sessionIdentifier)
按照 官方 Dropbox Objective-C SDK 中的描述设置 Info.plist
。 此外,以下常量必须设置一次,例如,在您的 app delegate 中
let appKey = ... // your Dropbox app key
let sharedContainerIdentifier = ... // optional: only needed if you want to create a `DropboxProvider` in an app extension and set `forceForegroundSession = false`
let keychainService = ... // the service name for the keychain, use `nil` to use default
let forceForegroundSession = ... // if set to `true`, all network requests are made on foreground sessions (by default, most download/upload operations are performed with a background session)
DropboxSetup.constants = DropboxSetup(appKey: appKey, sharedContainerIdentifier: sharedContainerIdentifier, keychainService: keychainService, forceForegroundSession: forceForegroundSession)
开始身份验证流程
let dropboxAuthenticator = DropboxAuthenticator()
let viewController = ... // the presenting `UIViewController`
dropboxAuthenticator.authenticate(from: viewController).then { credential in
// do something with `DropboxCredential`
// you probably want to save `credential.tokenUID` to re-create the credential later
}.catch { error in
// error handling
}
在您的 app delegate 中处理身份验证流程完成后,重定向
func application(_: UIApplication, open url: URL, options _: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
let canHandle = DBClientsManager.handleRedirectURL(url) { authResult in
guard let authResult = authResult else {
return
}
if authResult.isSuccess() {
let tokenUID = authResult.accessToken.uid
let credential = DropboxCredential(tokenUID: tokenUID)
DropboxAuthenticator.pendingAuthentication?.fulfill(credential)
} else if authResult.isCancel() {
DropboxAuthenticator.pendingAuthentication?.reject(DropboxAuthenticatorError.userCanceled)
} else if authResult.isError() {
DropboxAuthenticator.pendingAuthentication?.reject(authResult.nsError)
}
}
return canHandle
}
使用凭据创建一个 Dropbox 提供程序
let tokenUID = ... // the `tokenUID` you saved after the successful authentication flow
let credential = DropboxCredential(tokenUID: tokenUID)
let provider = DropboxCloudProvider(credential: credential)
按照 AppAuth 中的描述修改您的 app delegate。 此外,以下常量必须设置一次,例如,在您的 app delegate 中
let clientId = ... // your Google Drive client identifier
let redirectURL = ...
let sharedContainerIdentifier = ... // optional: only needed if you want to create a `GoogleDriveProvider` with a background `URLSession` in an app extension
GoogleDriveSetup.constants = GoogleDriveSetup(clientId: clientId, redirectURL: redirectURL, sharedContainerIdentifier: sharedContainerIdentifier)
开始身份验证流程
let tokenUID = ... // optional: you might want to give this credential an identifier, defaults to a random UUID
let credential = GoogleDriveCredential(tokenUID: tokenUID)
let viewController = ... // the presenting `UIViewController`
GoogleDriveAuthenticator.authenticate(credential: credential, from: viewController).then {
// authentication successful
}.catch { error in
// error handling
}
然后,您可以使用凭据创建一个 Google Drive 提供程序
let provider = GoogleDriveCloudProvider(credential: credential)
或者使用后台 URLSession 创建一个 Google Drive 提供程序
let sessionIdentifier = ...
let provider = GoogleDriveCloudProvider.withBackgroundSession(credential: credential, sessionIdentifier: sessionIdentifier)
按照 MSAL 中的描述设置 Info.plist
和您的 app delegate。 此外,以下常量必须设置一次,例如,在您的 app delegate 中
let clientApplication = ... // your `MSALPublicClientApplication`
let sharedContainerIdentifier = ... // optional: only needed if you want to create a `OneDriveProvider` with a background `URLSession` in an app extension
OneDriveSetup.constants = OneDriveSetup(clientApplication: clientApplication, sharedContainerIdentifier: sharedContainerIdentifier)
开始身份验证流程
let viewController = ... // the presenting `UIViewController`
OneDriveAuthenticator.authenticate(from: viewController).then { credential in
// do something with `OneDriveCredential`
// you probably want to save `credential.identifier` to re-create the credential later
}.catch { error in
// error handling
}
然后,您可以使用凭据创建一个 OneDrive 提供程序
let provider = OneDriveCloudProvider(credential: credential)
或者使用后台 URLSession 创建一个 OneDrive 提供程序
let sessionIdentifier = ...
let provider = OneDriveCloudProvider.withBackgroundSession(credential: credential, sessionIdentifier: sessionIdentifier)
以下常量必须设置一次,例如,在您的 app delegate 中
let appKey = ... // your pCloud app key
let sharedContainerIdentifier = ... // optional: only needed if you want to create a `OneDriveProvider` with a background `URLSession` in an app extension
PCloudSetup.constants = PCloudSetup(appKey: appKey, sharedContainerIdentifier: sharedContainerIdentifier)
开始身份验证流程
let viewController = ... // the presenting `UIViewController`
PCloudAuthenticator.authenticate(from: viewController).then { credential in
// do something with `PCloudCredential`
// you probably want to save `credential.user` to re-create the credential later
}.catch { error in
// error handling
}
然后,您可以使用凭据创建一个带有 pCloud 客户端的 pCloud 提供程序
let client = PCloud.createClient(with: credential.user)
let provider = PCloudCloudProvider(client: client)
或者使用后台 URLSession 创建一个带有 pCloud 客户端的 pCloud 提供程序
let sessionIdentifier = ...
let client = PCloud.createBackgroundClient(with: credential.user, sessionIdentifier: sessionIdentifier)
let provider = PCloudCloudProvider(client: client)
创建一个 S3 凭据
let accessKey = ...
let secretKey = ...
let url = ... // Note: the URL should not already contain the bucket name
let bucket = ... // Note: the bucket should already exist
let region = ...
let identifier = ... // optional: you might want to give this credential an identifier, defaults to a random UUID
let credential = S3Credential(accessKey: accessKey, secretKey: secretKey, url: url, bucket: bucket, region: region, identifier: identifier)
然后,您可以使用凭据创建一个 S3 提供程序
let provider = try S3Provider(credential: credential)
或者使用后台 URLSession 创建一个 S3 提供程序
let sharedContainerIdentifier = ... // optional: only needed if you want to create a `S3CloudProvider` in an app extension
let provider = try S3CloudProvider.withBackgroundSession(credential: credential, sharedContainerIdentifier: sharedContainerIdentifier)
理论上,您可以不经过进一步检查直接使用该提供程序。 但是,您应该使用 S3 验证器验证 S3 凭据
let credential = ...
S3Authenticator.verifyCredential(credential).then {
// credential validation successful
}.catch { error in
// error handling
}
创建一个 WebDAV 凭据
let baseURL = ...
let username = ...
let password = ...
let allowedCertificate = ... // optional: you might want to allowlist a TLS certificate
let identifier = ... // optional: you might want to give this credential an identifier, defaults to a random UUID
let credential = WebDAVCredential(baseURL: baseURL, username: username, password: password, allowedCertificate: allowedCertificate, identifier: identifier)
然后,您可以使用凭据创建一个带有 WebDAV 客户端的 WebDAV 提供程序
let client = WebDAVClient(credential: credential)
let provider = WebDAVProvider(with: client)
或者使用后台 URLSession 创建一个带有 WebDAV 客户端的 WebDAV 提供程序
let sessionIdentifier = ...
let sharedContainerIdentifier = ... // optional: only needed if you want to create a `WebDAVProvider` in an app extension
let client = WebDAVClient.withBackgroundSession(credential: credential, sessionIdentifier: sessionIdentifier, sharedContainerIdentifier: sharedContainerIdentifier)
let provider = WebDAVProvider(with: client)
理论上,您可以不经过进一步检查直接使用该提供程序。 但是,您应该使用 WebDAV 验证器验证 WebDAV 客户端及其凭据
let client = ...
WebDAVAuthenticator.verifyClient(client: client).then {
// client validation successful
}.catch { error in
// error handling
}
此外,对于允许证书,您可以使用 TLS 证书验证器
let baseURL = ...
let validator = TLSCertificateValidator(baseURL: baseURL)
validator.validate().then { certificate in
// certificate of type `TLSCertificate` contains several properties for further handling
}.catch { error in
// error handling
}
由于本地文件系统实际上不是云存储服务,因此命名可能令人困惑。 但是,可以通过本地文件系统访问 iCloud Drive,并且此提供程序包含用于处理卸载项的代码。
使用根 URL 创建一个本地文件系统提供程序
let rootURL = ... // rootURL.isFileURL must be `true`
let provider = LocalFileSystemProvider(rootURL: rootURL)
在调用此提供程序的功能时,应提供相对于根 URL 的云路径。
此提供程序使用 NSFileCoordinator
进行其操作,并支持异步访问。
此 SDK 使用 CocoaLumberjack 进行日志记录。 CocoaLumberjack 是一个灵活、快速的开源日志记录框架。 它支持许多功能,包括为每个输出目标设置日志记录级别,例如,将简洁的消息记录到控制台,并将详细的消息记录到日志文件。
CocoaLumberjack 日志记录级别是可加的,这样,当级别设置为 verbose 时,将记录来自 verbose 以下级别的所有消息。 也可以设置自定义日志记录以满足您的需求。 有关更多信息,请参见 CocoaLumberjack。
dynamicCloudAccessLogLevel = .verbose
以下日志记录级别选项可用
.off
.error
.warning
.info
.debug
.verbose
.all
定义日志输出目标的工作方式与 CocoaLumberjack
相同,唯一的区别是使用 CloudAccessDDLog.add()
而不是 DDLog.add()
添加 logger。 例如
CloudAccessDDLog.add(DDOSLogger.sharedInstance) // Uses os_log
let fileLogger: DDFileLogger = DDFileLogger() // File Logger
fileLogger.rollingFrequency = 60 * 60 * 24 // 24 hours
fileLogger.logFileManager.maximumNumberOfLogFiles = 7
CloudAccessDDLog.add(fileLogger)
您可以 在此处 了解有关云提供商集成测试的更多信息。
如果您想报告错误、提出问题或帮助我们进行编码,请阅读我们的 贡献指南。
该项目使用 SwiftFormat 和 SwiftLint 来强制执行代码样式和约定。 如果您尚未安装这些工具,请安装它们。
请确保您的代码格式正确并传递 linter 验证。 最简单的方法是设置一个 pre-commit hook。 在 .git/hooks/pre-commit
创建一个文件,内容如下:
./Scripts/process.sh --staged
exit $?
并使您的 pre-commit hook 可执行
chmod +x .git/hooks/pre-commit
帮助我们保持 Cryptomator 的开放性和包容性。 请阅读并遵守我们的 行为准则。
该项目在 AGPLv3(针对 FOSS 项目)以及源自 LGPL(针对独立软件供应商和经销商)的商业许可证下获得双重许可。 如果您想在未根据 AGPL 许可的应用程序中使用此库,请随时联系我们的 销售团队。