使用Swift添加项目和查询iOS Keychain [英] Adding Items to and Querying the iOS Keychain with Swift

查看:87
本文介绍了使用Swift添加项目和查询iOS Keychain的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法转换所有 Objective C 代码示例,这些示例可用于添加数据并从 iOS Keychain查询数据进入 Swift 。我正在尝试对字符串(访问令牌)进行基本存储并将其读回。我已经看过Stack Overflow上的其他一些问题,但我无法让它工作。我试图拼凑各种来源的解决方案。



编辑1:我尝试了更基本的设置,因为我想我的self.defaultKeychainQuery可能搞砸了。我已将下面的代码更新为最新版本。



编辑2:让它正常工作。我没有正确地将数据值添加到保存查询中。我需要将字符串转换为NSData。我已将下面的代码更新为最新的工作版本。



编辑3:正如Xerxes指出的那样,此代码不会由于字典的某些问题,使用高于Beta 1的Xcode版本。如果你知道对此的修复,请告诉我。



更新:我把它变成了用Swift编写的钥匙串库叫做Locksmith






保存

  class func save(service:NSString,data:NSString){
var dataFromString :NSData = data.dataUsingEncoding(NSUTF8StringEncoding,allowLossyConversion:false)
//实例化新的默认钥匙串查询
var keychainQuery:NSMutableDictionary = NSMutableDictionary(objects:[kSecClassGenericPassword,service,userAccount,dataFromString],forKeys: [kSecClass,kSecAttrService,kSecAttrAccount,kSecValueData])

//删除所有现有项目
SecItemDelete(keychainQuery as CFDictionaryRef)

//添加新的钥匙串项目
var status:OSStatus = SecItemAdd(keychainQuery as CFDictionaryRef,nil)

//检查它是否为worke d ok
println(保存状态代码为:\(状态))
}

加载

  class func load(service:NSString) - > AnyObject? {
//实例化一个新的默认钥匙串查询
//告诉查询返回结果
//将我们的结果限制为一个项
var keychainQuery:NSMutableDictionary = NSMutableDictionary(objects :[kSecClassGenericPassword,service,userAccount,kCFBooleanTrue,kSecMatchLimitOne],forKeys:[kSecClass,kSecAttrService,kSecAttrAccount,kSecReturnData,kSecMatchLimit])



//我也不是确定这里发生了什么...
var dataTypeRef:Unmanaged< AnyObject>?

//搜索钥匙串项目
let status:OSStatus = SecItemCopyMatching(keychainQuery,& dataTypeRef)


println(正在加载状态代码是:\(状态))

//我不太确定这里发生了什么......
让opaque = dataTypeRef?.toOpaque()

如果让op = opaque? {
let retrieveData = Unmanaged< NSData> .fromOpaque(op).takeUnretainedValue()
println(从钥匙串中检索以下数据:\(retrieveData))
var str = NSString(数据:被检索的数据,编码:NSUTF8StringEncoding)
println(已解码的字符串是\(str))
} else {
println(没有从钥匙串中检索到任何内容。 )
}

返回nil
}

用法(视图控制器)

  KeychainService.saveToken(sometoken)
KeychainService。 loadToken()

使用这些便利方法

  class func saveToken(token:NSString){
self.save(service,data:token)
}

class func loadToken(){
var token = self.load(service)
if let t = token {
println(令牌是:\(t))
}
}

这导致控制台中的输出:

 保存状态代码为:0 
加载状态代码为:0
从钥匙串中检索以下数据:< 736f6d65 746f6b65 6e>
解码后的字符串是

非常感谢您的帮助。我不太确定如果我得到了dataTypeRef,或者如果它有任何给定上面代码的数据,该怎么办。

解决方案

为了使其工作,您需要检索钥匙串常量的保留值,然后先存储,如下所示:

 让kSecClassValue = kSecClass.takeRetainedValue()as NSString 
let kSecAttrAccountValue = kSecAttrAccount.takeRetainedValue()as NSString
let kSecValueDataValue = kSecValueData.takeRetainedValue()as NSString
let kSecClassGenericPasswordValue = kSecClassGenericPassword.takeRetainedValue()as NSString
let kSecAttrServiceValue = kSecAttrService.takeRetainedValue()as NSString
let kSecMatchLimitValue = kSecMatchLimit.takeRetainedValue()as NSString
let kSecReturnDataValue = kSecReturnData.takeRetainedValue()as NSString
让kSecMatchLimitOneValue = kSecMatchLimitOne.takeRetainedValue()为NSString

你可以然后引用NSMutableDictionary中的值,如下所示:

  var keychainQuery:NSMutableDictionary = NSMutableDictionary(objects:[kSecClassGenericPasswordValue,service,userAccount, kCFBooleanTrue,kSecMatchLimitOneValue],forKeys:[kSecClassValue,kSecAttrServiceValue,kSecAttrAccountValue,kSecReturnDataValue,kSecMatchLimitValue])

我写的关于它的博客文章:
http://rshelby.com/2014/08/using-swift-to-save-and-query-ios-keychain-in-xcode-beta-4/ / p>

希望这有帮助!



rshelby


I'm having trouble converting all of the Objective C code samples that are available for adding data and querying data from the iOS Keychain into Swift. I'm trying to do a basic storage of a string (an access token) and reading it back. I've had a look at some of the other questions on Stack Overflow, but I can't quite get it to work. I've tried to piece together a solution from the various sources.

Edit 1: I tried with a more basic setup, because I thought my self.defaultKeychainQuery might have been messing things up. I've updated the code below to the latest version.

Edit 2: Got it working. I wasn't adding the data value to the save query properly. I needed to convert the string to NSData. I've updated the code below to the most recent working version.

Edit 3: As Xerxes points out below, this code doesn't work with Xcode versions higher than Beta 1 because of some issue with Dictionaries. If you know of a fix for this, please let me know.

Update: I turned this into a keychain library written in Swift called Locksmith.


Save

class func save(service: NSString, data: NSString) {
  var dataFromString: NSData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
  // Instantiate a new default keychain query
  var keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPassword, service, userAccount, dataFromString], forKeys: [kSecClass, kSecAttrService, kSecAttrAccount, kSecValueData])

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

  // Add the new keychain item
  var status: OSStatus = SecItemAdd(keychainQuery as CFDictionaryRef, nil)

  // Check that it worked ok
  println("Saving status code is: \(status)")
}

Load

  class func load(service: NSString) -> AnyObject? {
    // Instantiate a new default keychain query
    // Tell the query to return a result
    // Limit our results to one item
    var keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPassword, service, userAccount, kCFBooleanTrue, kSecMatchLimitOne], forKeys: [kSecClass, kSecAttrService, kSecAttrAccount, kSecReturnData, kSecMatchLimit])



    // I'm not too sure what's happening here...
    var dataTypeRef :Unmanaged<AnyObject>?

    // Search for the keychain items
    let status: OSStatus = SecItemCopyMatching(keychainQuery, &dataTypeRef)


    println("Loading status code is: \(status)")

    // I'm not too sure what's happening here...
    let opaque = dataTypeRef?.toOpaque()

    if let op = opaque? {
      let retrievedData = Unmanaged<NSData>.fromOpaque(op).takeUnretainedValue()
      println("Retrieved the following data from the keychain: \(retrievedData)")
      var str = NSString(data: retrievedData, encoding: NSUTF8StringEncoding)
      println("The decoded string is \(str)")
    } else {
      println("Nothing was retrieved from the keychain.")
    }

    return nil
  }

Usage (view controller)

KeychainService.saveToken("sometoken")
KeychainService.loadToken()

which uses these convenience methods

class func saveToken(token: NSString) {
    self.save("service", data: token)
  }

class func loadToken() {
    var token = self.load("service")
    if let t = token {
      println("The token is: \(t)")
    }
  }

This leads to the output in the console:

Saving status code is: 0
Loading status code is: 0
Retrieved the following data from the keychain: <736f6d65 746f6b65 6e>
The decoded string is sometoken

Thanks a lot for your help. I'm not too sure what to do with dataTypeRef once I've got it, or if it has any data given the code above.

解决方案

In order to get this to work, you will need to retrieve the retained values of the keychain constants and store then first like so:

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

You can then reference the values in the NSMutableDictionary like so:

var keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, userAccount, kCFBooleanTrue, kSecMatchLimitOneValue], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecReturnDataValue, kSecMatchLimitValue])

I wrote a blog post about it at: http://rshelby.com/2014/08/using-swift-to-save-and-query-ios-keychain-in-xcode-beta-4/

Hope this helps!

rshelby

这篇关于使用Swift添加项目和查询iOS Keychain的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆