继承 HTTPConnection 类:
@interface MyHTTPConnection : HTTPConnection
在 HTTPConnection
子类中,实现 - (BOOL)isSecureServer 方法并返回 YES,表示支持 https。
制作一个 SSL 自签名证书,安装到钥匙串,然后导出为 .p12 文件,记住导出密码。
制作证书时需要注意 /CN 参数必须指定主机名,比如 /CN 参数指定为 127.0.0.1,则访问时只能用 https://127.0.0.1,而不能用 https://localhost 替代。
实现 sslIdentityAndCertificates 方法:
- (NSArray *)sslIdentityAndCertificates
{
SecIdentityRef identityRef = NULL;
SecCertificateRef certificateRef = NULL;
SecTrustRef trustRef = NULL;
NSString *thePath = [[NSBundle mainBundle] pathForResource:@"127.0.0.1" ofType:@"p12"];
NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
CFStringRef password = CFSTR("你导出 .p12 的密码");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
OSStatus securityError = errSecSuccess;
securityError = SecPKCS12Import(inPKCS12Data, optionsDictionary, &items);
if (securityError == 0) {
CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);
const void *tempIdentity = NULL;
tempIdentity = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemIdentity);
identityRef = (SecIdentityRef)tempIdentity;
const void *tempTrust = NULL;
tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);
trustRef = (SecTrustRef)tempTrust;
} else {
NSLog(@"Failed with error code %d",(int)securityError);
return nil;
}
SecIdentityCopyCertificate(identityRef, &certificateRef);
NSArray *result = [[NSArray alloc] initWithObjects:(__bridge id)identityRef, (__bridge id)certificateRef, nil];
return result;
}
复制 HTTPConnetion.m 中的 startConnection 方法和 startReadingRequest 方法代码。
找到 startConnection 方法中如下语句:
[settings setObject:(NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL forKey:(NSString *)kCFStreamSSLLevel]
替换为:
[settings setObject:[NSNumber numberWithInteger:2] forKey:GCDAsyncSocketSSLProtocolVersionMin];
[settings setObject:[NSNumber numberWithInteger:2] forKey:GCDAsyncSocketSSLProtocolVersionMax];
在启动 HTTPServer (调用 startServer )之前,使用 setConnectionClass 方法将 HTTPConnecdtion 替换为 MyHTTPConnection:
[httpServer setConnectionClass:[MyHTTPConnection class]];