无法使用Swift中的Network Extension Framework iOS 8设置VPN连接

所以我一直在尝试使用iOS 8networking扩展框架来build立一个VPN连接,当用户按UIButton。 我已经使用了以下教程: http : //ramezanpour.net/post/2014/08/03/configure-and-manage-vpn-connections-programmatically-in-ios-8/

但由于某种原因,它不断要求的VPN密码和共享的秘密。 即使我设置了passwordReference和sharedSecretReference。 如果在安assembly置文件时input这些详细信息,它仍然不起作用。 它只是在使用框架开始连接时不做任何事情。 当尝试使用设置应用程序进行连接时,会显示“没有sharedSecret”错误。

这是我用来build立连接的代码。

func toggleConnection(sender: UIButton) { if(!self.connected){ self.manager.loadFromPreferencesWithCompletionHandler { (error) -> Void in if((error) != nil) { println("VPN Preferences error: 1") } else { var p = NEVPNProtocolIPSec() p.username = "$username" p.serverAddress = "$vpn" p.passwordReference = KeychainService.dataForKey("vpnPassword")! println(p.passwordReference) p.authenticationMethod = NEVPNIKEAuthenticationMethod.SharedSecret p.sharedSecretReference = KeychainService.dataForKey("sharedSecret")! println(p.sharedSecretReference) p.localIdentifier = "vpn" p.remoteIdentifier = "vpn" p.disconnectOnSleep = false self.manager.`protocol` = p self.manager.onDemandEnabled = true self.manager.localizedDescription = "VPN" self.manager.saveToPreferencesWithCompletionHandler({ (error) -> Void in if((error) != nil) { println("VPN Preferences error: 2") println(error) } else { var startError: NSError? self.manager.connection.startVPNTunnelAndReturnError(&startError) if((startError) != nil) { println("VPN Preferences error: 3") println(startError) } else { println("Start VPN") } } }) } } } } 

这些是我用作钥匙链参考的function。

 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 } 

任何帮助表示赞赏!

所以我必须最终用以下Obj-C方法replace我用来访问钥匙串的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:@"VPN" 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:@"VPN" 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; }