因此,当用户按下UIButton时,我一直在尝试使用iOS 8网络扩展框架来设置VPN连接。 我使用了以下教程:http://ramezanpour.net/post/2014/08/03/configure-and-manage-vpn-connections-programmatically-in-ios-8/
但由于某种原因,它不断要求输入密码和共享密码。即使我设置了passwordReference和sharedSecretReference。 如果我在安装配置文件时输入这些详细信息,它仍然无法正常工作。使用框架启动连接时,它不会做任何事情。当尝试使用设置应用程序进行连接时,它会给出一个"没有共享秘密"错误。
这是我用来设置连接的代码。
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")
}
}
})
}
}
}
}
这些是我用作钥匙串参考的功能。
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
}
任何帮助表示赞赏!
答案 0 :(得分:2)
所以我不得不用以下的Obj-C方法替换我用来访问keychain的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;
}