钥匙串 + adhoc 分发

4

首先,一些细节:我们正在开发一个iOS应用程序,目前使用Swift / Xcode 6.1 GM 2进行开发。

当分发应用程序时,我们在密钥链访问方面遇到了一些混乱的问题,并且无法追踪原因。所有的配置文件都与我们的应用程序捆绑名称匹配。虽然我们使用TestFlight进行分发,但我不认为它是问题所在。

我们只能使其在之前未安装该应用程序的iOS 7设备上运行。没有一个iOS 8设备可以自主工作。我们最初得到的错误是25300(errSecItemNotFound),现在重置配置文件后,我们得到了一个简单的0(在保存和加载时仍然无法检索到数据)。从Xcode部署开发构建时,一切正常。

我已将我们使用的密钥链包装器代码分离出来:

import UIKit
import Security

let serviceIdentifier = "com.Test.KeychainTest"

let kSecClassValue = kSecClass as NSString
let kSecAttrAccountValue = kSecAttrAccount as NSString
let kSecValueDataValue = kSecValueData as NSString
let kSecClassGenericPasswordValue = kSecClassGenericPassword as NSString
let kSecAttrServiceValue = kSecAttrService as NSString
let kSecMatchLimitValue = kSecMatchLimit as NSString
let kSecReturnDataValue = kSecReturnData as NSString
let kSecMatchLimitOneValue = kSecMatchLimitOne as NSString

class KeychainManager {

class func setString(value: NSString, forKey: String) {
    self.save(serviceIdentifier, key: forKey, data: value)
}

class func stringForKey(key: String) -> NSString? {
    var token = self.load(serviceIdentifier, key: key)

    return token
}

class func removeItemForKey(key: String) {
    self.save(serviceIdentifier, key: key, data: "")
}



class func save(service: NSString, key: String, data: NSString) {
    var dataFromString: NSData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
    // Instantiate a new default keychain query
    var keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, key, dataFromString], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecValueDataValue])

    // Delete any existing items
    SecItemDelete(keychainQuery as CFDictionaryRef)

    if data == "" { return }

    // Add the new keychain item
    var status: OSStatus = SecItemAdd(keychainQuery as CFDictionaryRef, nil)
    var alertView = UIAlertView();
    alertView.addButtonWithTitle("Ok");
    alertView.title = "Status";
    alertView.message = "Saving \(status)";
    alertView.show();
}

class func load(service: NSString, key: String) -> NSString? {
    // Instantiate a new default keychain query
    // Tell the query to return a result
    // Limit our results to one item
    var keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, key, kCFBooleanTrue, kSecMatchLimitOneValue], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecReturnDataValue, kSecMatchLimitValue])

    var dataTypeRef :Unmanaged<AnyObject>?

    // Search for the keychain items
    let status: OSStatus = SecItemCopyMatching(keychainQuery, &dataTypeRef)
    var alertView = UIAlertView();
    alertView.addButtonWithTitle("Ok");
    alertView.title = "Status";
    alertView.message = "Loading \(status)";
    alertView.show();

    let opaque = dataTypeRef?.toOpaque()

    var contentsOfKeychain: NSString?

    if let op = opaque? {
        let retrievedData = Unmanaged<NSData>.fromOpaque(op).takeUnretainedValue()

        // Convert the data retrieved from the keychain into a string
        contentsOfKeychain = NSString(data: retrievedData, encoding: NSUTF8StringEncoding)
    } else {
        return nil
    }

    return contentsOfKeychain
}


}
  1. 我们可能漏掉了什么吗?
  2. 如何最好地排除这个问题?我们在日志/ iPhone配置实用程序中没有从密钥链收到任何错误。目前,我只是将一些简单的警报放入代码中,以确定操作状态。
2个回答

2

在配置文件和钥匙链代码中一切似乎都很好。问题出现在Swift编译器的设置上...将“Release”优化级别从“Fastest”更改为“None”,这似乎可以解决问题。

enter image description here


考虑到Swift在没有优化的情况下运行速度非常慢,这个解决方案很糟糕。也许关闭单个文件的优化会更好。 - Jon Shier
@jshier,您能否解释一下如何为单个文件执行此操作? - Wojtek Turowicz
在您的目标“Build Phases”->“Compile Sources”中,双击“Compiler Flags”列并添加-Onone设置。 - Jon Shier
@jshier 感谢您的评论。我们会尝试一下,看看它的表现如何 :) - Mark

1
请确保您还为kSecAttrAccessible指定了值。可能还需要为kSecAttrAccessControl指定值,它在iOS8中添加

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接