如何在特定钥匙串访问组中保存访问令牌/从中获取访问令牌

时间:2019-04-30 14:00:00

标签: ios objective-c

如何将JSON Web令牌保存到特定的钥匙串访问组,以及如何使用Objective-c从钥匙串中检索此令牌? (我想不使用任何钥匙扣包装器就可以做到这一点。)

3 个答案:

答案 0 :(得分:0)

您确实可以使用Apple提供的C API在钥匙串中存储/​​检索/删除值。我想澄清一下您已经收到的答案:完全不建议将JWT存储在“用户默认值”中,因为存储在其中的任何内容都被视为纯文本,并损害了数据/ API的安全性。您可以通过FileManager访问该应用程序的捆绑包并在没有问题的情况下找到preferences.plist来进行验证。

现在,回到您的问题,我可以提供一些帮助,但是我缺少访问特定钥匙串访问组的部分,尽管应该不复杂...

因此,此步骤总结了钥匙串的一般用法:

  • 由于钥匙串是一个SQLite3数据库,因此您需要先创建一个查询
  • 在其中存储内容时不会检查重复项,因此您需要先删除当前项,然后再添加新项以保持原样,如果您要删除的项不存在,则不会执行任何操作。
  • 将项目(查询)添加到KeyChain中。

这里是Swift中的一个示例,请理解它,以便您可以轻松地将其翻译为ObjC:

// value is anything you want to store, let's say "Hello Jobs", and you need to
convert that value to data.

if let valueData = value.data(using: .utf8) {
        return [kSecClass as String: kSecClassGenericPassword as String,
                kSecAttrAccount as String: key,
                kSecValueData as String: valueData] as [String:Any]
    }

SecItemDelete(query as CFDictionary) // Delete the query if exists
SecItemAdd(query as CFDictionary, nil) // Store your value

如您所见,您需要将查询强制转换为CFDictionary,因为这就是C API作为参数接收的预期类型。

现在要检索存储的值,您需要执行以下操作:

// You need a query again, but this time you add extra parameters to indicate you want to return the value as data using the boolean below and to limit the query to just 1 item.
let query = [kSecClass as String: kSecClassGenericPassword as String,
                 kSecAttrAccount as String: key,
                 kSecReturnData as String: kCFBooleanTrue,
                 kSecMatchLimit as String: kSecMatchLimitOne] as [String: Any]

// You define a var to use its reference (memory address) as its required by the SecItemCopyMatching API so it can store the outcome of the query there.
    var dataTypeRef: AnyObject?
    let status: OSStatus = SecItemCopyMatching(query as CFDictionary, &dataTypeRef)
    if status == noErr {
        return dataTypeRef as? Data // If the query was successful you retrieve the data by casting your previously defined var to a Data type
    }

这里唯一要做的就是将检索到的Data值转换为所需的值,在这种情况下,它将是一个String,因为这就是JWT的类型。

希望您可以以此为指导,我敢打赌,您需要为查询添加一个额外的值,才能使用您要从中获取数据的特定钥匙串组。

答案 1 :(得分:0)

要将令牌保存到特定的钥匙串访问组,首先需要在Apple Developer控制台中创建与您的应用程序ID关联的钥匙串访问组。然后,为您的应用程序ID授予访问该访问组的权利。这应该给您一个如下所示的权利文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" 
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>keychain-access-groups</key>
    <array>
        <string>656CMN2Q97.com.mycompany.myapp</string>
    </array>
</dict>
</plist>

然后,对其进行读写就这么简单:

NSString *kapiToken = @"apiToken";
NSString *kServices = @"Services";

self.apiToken = [UICKeyChainStore stringForKey:kapiToken service:kServices];

....

[UICKeyChainStore setString:self.apiToken forKey:kapiToken service:kServices];

答案 2 :(得分:-1)

就我所能提供的帮助来说,如果没有钥匙串包装器,您将无法访问钥匙串商店。为了安全起见,Apple没有打开没有Keychain包装器的API来访问Keychain商店。希望这会有所帮助。

您可以将令牌存储在 Singleton 类中,因为我认为该令牌将在每次应用重新启动时刷新。如果不是这种情况,还可以将其存储在NSUserDefaults中。