保存配置faild当我配置iOS 8.0 VPN连接时

时间:2016-03-16 04:55:17

标签: objective-c ios8 vpn

我使用Network Extension框架来配置和管理VPN连接。当我运行我的代码时,它将记录错误消息:"保存配置faild [(null)]"在我完成安装配置文件之前。我编写了如下代码:

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

self.vpnManager = [NEVPNManager sharedManager];
[_vpnManager loadFromPreferencesWithCompletionHandler:^(NSError * _Nullable error) {
    if (error) {
        NSLog(@"Load config failed [%@]", error.localizedDescription);
        return ;
    }
    // config IPSec protocol
    NEVPNProtocolIKEv2 *p = _vpnManager.protocol;
    if (p) {

    }else{
        p = [[NEVPNProtocolIKEv2 alloc]init];
    }

    p.username = @"qlvpn";
    p.serverAddress = @"my serverAddress";

    // get password persistent reference from keychain


    p.passwordReference = [self searchKeychainCopyMatching:@"kd2014@"];
    // If password doesn't exist in keychain, should create it beforehand.
    if (!p.passwordReference) {
        [self createKeychainValue:@"kd2014@" forIdentifier:@"kd2014@"];
         p.passwordReference = [self searchKeychainCopyMatching:@"kd2014@"];
    }
    p.authenticationMethod = NEVPNIKEAuthenticationMethodSharedSecret;
    p.sharedSecretReference = [self searchKeychainCopyMatching:@"PSK"];
    if (!p.sharedSecretReference) {
        [self createKeychainValue:@"qlvpn_kd2014@" forIdentifier:@"PSK"];
        p.sharedSecretReference = [self searchKeychainCopyMatching:@"PSK"];
    }

    p.localIdentifier = @"qlvpn.client";
    p.remoteIdentifier = @"qlvpn.server";

    p.useExtendedAuthentication = YES;
    p.disconnectOnSleep = NO;
    _vpnManager.protocol = p;
    _vpnManager.localizedDescription = @"IKEv2 Demo";

    [_vpnManager saveToPreferencesWithCompletionHandler:^(NSError * _Nullable error) {
        NSLog(@"Save config faild[%@]",error.localizedDescription);
    }];

}];

}

keyChain方法如下:

    static NSString * const serviceName = @"qlvpn.vpn_config";

- (NSMutableDictionary *)newSearchDictionary:(NSString *)identifier {
    NSMutableDictionary *searchDictionary = [[NSMutableDictionary alloc] init];

    [searchDictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];

    NSData *encodedIdentifier = [identifier dataUsingEncoding:NSUTF8StringEncoding];
    [searchDictionary setObject:encodedIdentifier forKey:(__bridge id)kSecAttrGeneric];
    [searchDictionary setObject:encodedIdentifier forKey:(__bridge id)kSecAttrAccount];
    [searchDictionary setObject:serviceName forKey:(__bridge id)kSecAttrService];

    return searchDictionary;
}

- (NSData *)searchKeychainCopyMatching:(NSString *)identifier {
    NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier];

    // Add search attributes
    [searchDictionary setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];

    // Add search return types
    // Must be persistent ref !!!!
    [searchDictionary setObject:@YES forKey:(__bridge id)kSecReturnPersistentRef];

    CFTypeRef result = NULL;
    SecItemCopyMatching((__bridge CFDictionaryRef)searchDictionary, &result);

    return (__bridge_transfer NSData *)result;
}

- (BOOL)createKeychainValue:(NSString *)password forIdentifier:(NSString *)identifier {
    NSMutableDictionary *dictionary = [self newSearchDictionary:identifier];

    OSStatus status = SecItemDelete((__bridge CFDictionaryRef)dictionary);

    NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
    [dictionary setObject:passwordData forKey:(__bridge id)kSecValueData];

    status = SecItemAdd((__bridge CFDictionaryRef)dictionary, NULL);

    if (status == errSecSuccess) {
        return YES;
    }
    return NO;
}

所以,我真的不知道为什么我不能保存配置..

1 个答案:

答案 0 :(得分:0)

除非我同时打电话,否则我无法保存它

loadAllFromPreferencesWithCompletionHandler
loadFromPreferencesWithCompletionHandler

然后才

saveToPreferencesWithCompletionHandler