2

我的 iOS 应用程序检查 iCloud 帐户状态,然后使用以下方法请求 iCloud WebToken:

@objc static func fetchWebAuthToken ( _ apiToken : String, _ callback : @escaping CCallbackFunctionWithBoolAndString )
{
    let fetchAuthorization = CKFetchWebAuthTokenOperation(apiToken: apiToken)

    fetchAuthorization.fetchWebAuthTokenCompletionBlock = { webToken, error in
        guard let webToken = webToken, error == nil else {
            callback ( false, "[SWIFT] fetchWebAuthToken() error. " + (error?.localizedDescription ?? ""));
            return;
        }

        let encodedWebToken = token.addingPercentEncoding (
                withAllowedCharacters: CharacterSet(charactersIn: "+/=").inverted
            ) ?? token

        callback ( true, encodedWebToken );
        return;
    }

    CKContainer.default().privateCloudDatabase.add(fetchAuthorization);
}

一切正常,并返回格式正确的 Web 令牌。

然后,我获取该 Web 令牌,并使用 Postman 形成请求(删除了确切的值):

https://api.apple-cloudkit.com/database/1/iCloud.com.[my container]/development/private/users/caller?ckAPIToken=[development container token]&ckWebAuthToken=[web token]

回应是:

{
  "uuid": "[abc]",
  "serverErrorCode": "ACCESS_DENIED",
  "reason": "private db access disabled for this account"
}

如果我改为请求公共数据库,我会得到有效且正确的响应:

https://api.apple-cloudkit.com/database/1/iCloud.com.[my container]/development/public/users/caller?ckAPIToken=[development container token]&ckWebAuthToken=[web token]

{
  "userRecordName": "_[user id]",
  "nameComponents": {
    "givenName": "[First Name]",
    "familyName": "[Surname]"
  }
}

所以,这里有两个问题。

1)如果我在代码中为私有数据库请求 Web 令牌,为什么它只允许我与公共数据库交互?感觉就像它提供了一个仅对公共数据库有效的 Web 令牌,而不管我将操作添加到哪个数据库。

2)像这样针对公共数据库验证用户的安全隐患是什么?令牌应在 30 分钟内过期,这在这方面有所帮助。

为了证明 Web 令牌对私有数据库有效,我在 Dashboard 中更新了“登录回调”,复制了生成的 ckWebAuthToken 并能够通过 PostMan 访问私有数据库,因此这没有问题。似乎问题完全在于从 iOS 代码返回的 Web 令牌。

4

1 回答 1

0

我的猜测是,这是因为UsersCloudKit 中的记录类型始终存储在每个 CloudKit 容器的公共数据库中。

这种针对公共数据库的验证不应该有任何安全风险。在我看来,Apple 不应该将其命名为“公开”,因为它并不是真正公开的。它只是对应用程序的用户普遍可用,但只有应用程序和经过身份验证的用户才能与开发人员定义的数据库进行交易。它不向公众开放。

我将假设您正在使用此身份验证流程做一些花哨的事情,因为在 iOS 设备上对用户进行身份验证不需要传递ckWebAuthToken. :)

于 2018-11-13T21:11:44.473 回答