无法在 Swift 中使用网络扩展框架 iOS 8 设置 *** 连接
Posted
技术标签:
【中文标题】无法在 Swift 中使用网络扩展框架 iOS 8 设置 *** 连接【英文标题】:Can't setup *** connection using Network Extension Framework iOS 8 in Swift 【发布时间】:2015-08-14 06:06:58 【问题描述】:所以我一直在尝试使用 ios 8 网络扩展框架在用户按下 UIButton 时设置 *** 连接。 我使用了以下教程:http://ramezanpour.net/post/2014/08/03/configure-and-manage-***-connections-programmatically-in-ios-8/
但由于某种原因,它一直要求提供 *** 密码和共享密钥。即使我设置了 passwordReference 和 sharedSecretReference。 如果我在安装配置文件时输入这些详细信息,它仍然无法工作。使用框架启动连接时,它什么也不做。尝试使用设置应用程序连接时,会出现“没有 sharedSecret”错误。
这是我用来建立连接的代码。
func toggleConnection(sender: UIButton)
if(!self.connected)
self.manager.loadFromPreferencesWithCompletionHandler (error) -> Void in
if((error) != nil)
println("*** Preferences error: 1")
else
var p = NE***ProtocolIPSec()
p.username = "$username"
p.serverAddress = "$***"
p.passwordReference = KeychainService.dataForKey("***Password")!
println(p.passwordReference)
p.authenticationMethod = NE***IKEAuthenticationMethod.SharedSecret
p.sharedSecretReference = KeychainService.dataForKey("sharedSecret")!
println(p.sharedSecretReference)
p.localIdentifier = "***"
p.remoteIdentifier = "***"
p.disconnectOnSleep = false
self.manager.`protocol` = p
self.manager.onDemandEnabled = true
self.manager.localizedDescription = "***"
self.manager.saveToPreferencesWithCompletionHandler( (error) -> Void in
if((error) != nil)
println("*** Preferences error: 2")
println(error)
else
var startError: NSError?
self.manager.connection.start***TunnelAndReturnError(&startError)
if((startError) != nil)
println("*** Preferences error: 3")
println(startError)
else
println("Start ***")
)
这些是我用作钥匙串参考的函数。
class func save(service: NSString, key: String, data: NSString)
var dataFromString: NSData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
var keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPassword, service, key, dataFromString], forKeys: [kSecClass, kSecAttrService, kSecAttrAccount, kSecValueData])
SecItemDelete(keychainQuery as CFDictionaryRef)
if data == "" return
var status: OSStatus = SecItemAdd(keychainQuery as CFDictionaryRef, nil)
println(status)
class func load(service: NSString, key: String) -> NSData?
var keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPassword, service, key, kCFBooleanTrue, kSecMatchLimitOne, kCFBooleanTrue], forKeys: [kSecClass, kSecAttrService, kSecAttrAccount, kSecReturnData, kSecMatchLimit, kSecReturnPersistentRef])
var dataTypeRef :Unmanaged<AnyObject>?
let status: OSStatus = SecItemCopyMatching(keychainQuery, &dataTypeRef)
println(status)
if (status != errSecSuccess)
return nil
let opaque = dataTypeRef?.toOpaque()
var contentsOfKeychain: NSData? = nil
if let op = opaque
let retrievedData = Unmanaged<NSData>.fromOpaque(op).takeUnretainedValue()
contentsOfKeychain = retrievedData
println(contentsOfKeychain)
return contentsOfKeychain
感谢任何帮助!
【问题讨论】:
【参考方案1】:所以我最终不得不用以下 Obj-C 方法替换用于访问钥匙串的 Swift 库。据我目前所知,这解决了我的问题。
+ (void) storeData: (NSString * )key data:(NSData *)data
NSLog(@"Store Data");
NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];
[dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
NSData *encodedKey = [key dataUsingEncoding:NSUTF8StringEncoding];
[dict setObject:encodedKey forKey:(__bridge id)kSecAttrGeneric];
[dict setObject:encodedKey forKey:(__bridge id)kSecAttrAccount];
[dict setObject:@"***" forKey:(__bridge id)kSecAttrService];
[dict setObject:(__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly forKey:(__bridge id)kSecAttrAccessible];
[dict setObject:data forKey:(__bridge id)kSecValueData];
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)dict, NULL);
if(errSecSuccess != status)
NSLog(@"Unable add item with key =%@ error:%d",key,(int)status);
+ (NSData *) getData: (NSString *)key
NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];
[dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
NSData *encodedKey = [key dataUsingEncoding:NSUTF8StringEncoding];
[dict setObject:encodedKey forKey:(__bridge id)kSecAttrGeneric];
[dict setObject:encodedKey forKey:(__bridge id)kSecAttrAccount];
[dict setObject:@"***" forKey:(__bridge id)kSecAttrService];
[dict setObject:(__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly forKey:(__bridge id)kSecAttrAccessible];
[dict setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
[dict setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnPersistentRef];
CFTypeRef result = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)dict,&result);
if( status != errSecSuccess)
NSLog(@"Unable to fetch item for key %@ with error:%d",key,(int)status);
return nil;
NSData *resultData = (__bridge NSData *)result;
return resultData;
【讨论】:
你好,手机在自动锁定时进入睡眠状态会断线吗? 如果您将p.disconnectOnSleep
设置为true
,则不会。
“userName”和“serverAddress”的值是什么?
我尝试使用您的代码,但是当我点击连接按钮时,我收到日志错误“无法完成操作。(NE***ErrorDomain 错误 1。)”
@Houwert 我附加了这些 Objective-C 方法,但我如何存储数据 // KeychainItemWrapper.storeData("shared", data: config.psk!) 我的 psk 是字符串,但 storeData 不采用“数据”一个字符串值我该如何解决这个问题?以上是关于无法在 Swift 中使用网络扩展框架 iOS 8 设置 *** 连接的主要内容,如果未能解决你的问题,请参考以下文章
mysql 字符集 utf 8 排序规则(dup 键)无法正常工作