无法在 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 设置 *** 连接的主要内容,如果未能解决你的问题,请参考以下文章

8.3 后无法在 Spotlight 中使用键盘扩展

Swift iOS Intent 扩展:无法读取数据,因为它的格式不正确

迁移到 Swift 3 时可以使用旧框架吗?

xcode gm ios 8 gm swift 今天扩展在模拟器和设备中崩溃:库未加载:@rpath/libswiftCore.dylib

Swift - Xcode 8 - iOS 10 - 无法创建简单约束

UIPopoverController、Xcode 6、IOS 8 使用 Swift