【问题标题】:CloudKit Server-to-Server auth: Keep getting 401 Authentication failedCloudKit 服务器到服务器身份验证:不断收到 401 身份验证失败
【发布时间】:2020-11-24 05:46:27
【问题描述】:

我最近一直在探索 CloudKit 和相关框架。我与我的应用程序以及使用 CloudKitJS 的网站进行了通信。我苦苦挣扎的是服务器到服务器的通信(我需要从 csv 中的 公共数据库 导出数据。

我已经尝试过其他人建议的 Python 包 requests-cloudkit。我创建了一个服务器到服务器令牌,并且在创建 eckey.pem 文件后仅复制了 START 和 END 行之间的密钥。然后我得到了这个代码:

from requests_cloudkit import CloudKitAuth
from restmapper import restmapper
import json
KEY_ID = '[my key ID from CK Dashboard]'
SECRET_FILE_KEY = 'eckey.pem'
AUTH = CloudKitAuth(KEY_ID, SECRET_FILE_KEY)
PARAMS = {
        'query':{
                'recordType': '[my record type]'
        },
}
CloudKit = restmapper.RestMapper("https://api.apple-cloudkit.com/database/1/[my container]/development/")
cloudkit = CloudKit(auth=AUTH)
response = cloudkit.POST.public.records.query(json.dumps(PARAMS))

然后我收到 401 Authentication failed 响应。我被困了好几天,所以我将不胜感激任何帮助或建议。 ????

【问题讨论】:

    标签: python authentication server cloudkit cloudkit-web-services


    【解决方案1】:

    创建服务器到服务器密钥是重要的第一步,但为了在此之后发出 HTTP 请求,您必须对每个请求进行签名。

    this documentation page 底部附近查找Authenticate Web Service Requests部分。

    这有点令人费解,但您必须仔细构建签名标头以包含在您发出的每个请求中。我不熟悉如何在 Python 中执行此操作,但我在 NodeJS 中执行此操作可能会有所帮助:

    //Get the timestamp in a very specific format
    let date = moment().utc().format('YYYY-MM-DD[T]HH:mm:ss[Z]')
    
    //Construct the subpath
    let endpoint = '/records/lookup'
    let path = '/database/1/iCloud.*****/development/public'
    let subpath = path+endpoint
    
    //Get the key file
    let privateKeyFile = fs.readFileSync('../../'+SECRET_FILE_KEY, 'utf8')
    
    //Make a string out of your JSON query
    let query = {
      recordType: '[my record type]'
    }
    let requestBody = JSON.stringify(query)
    
    //Hash the query
    let bodyHash = crypto.createHash('sha256').update(requestBody, 'utf8').digest('base64')
    
    //Assemble the components you just generated in a special format
    //[Current date]:[Request body]:[Web service URL subpath]
    let message = date+':'+bodyHash+':'+subpath
      
    //Sign it
    let signature = crypto.createSign('RSA-SHA256').update(message).sign(privateKeyFile, 'base64')
    
    //Assemble your headers and include them in your HTTP request
    let headers = {
      'X-Apple-CloudKit-Request-KeyID': KEY_ID,
      'X-Apple-CloudKit-Request-ISO8601Date': date,
      'X-Apple-CloudKit-Request-SignatureV1': signature
    }
    

    一开始这有点麻烦,但我只是将所有这些东西放在一个函数中,以便在我需要发出请求时重复使用。

    Apple 的文档几乎已被遗弃,如今很难找到有关 CloudKit Web Services 的良好帮助。

    【讨论】:

      猜你喜欢
      • 2016-05-16
      • 2019-11-06
      • 2016-05-17
      • 1970-01-01
      • 2020-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多