背景
- iOS移动端使用
CocoaAsyncSocket
通过本地HTTP Server与网页端交互 - 网页端支持 HTTPS的话,因为HTTP、HTTPS网页内容混合会导致请求异常
解决思路
- iOS移动端 HTTP Server 支持 HTTPS
- iOS移动端和网页端改为 Websocket 交互
我们这里选择 支持HTTPS,即为localhost
或 127.0.0.1
配置SSL证书
配置证书
自签证书的不安全性,并且浏览器会提示
不安全
,需要用户选择是否继续前往,所以不考虑,
公共证书的话,因为localhost
或 127.0.0.1
的不唯一性,是不允许生成公共SSL证书。
经过查找资料,可以通过自有域名指向127.0.0.1
来解决这个问题,
可通过 FreeSSL 为自由域名配置免费的SSL证书
最后下载证书会得到自由域名的SSL证书文件夹,包含如下:
导出p12
openssl pkcs12 -export -clcerts -in full_chain.pem -inkey private.key -out my.p12
iOS端配置
重写HTTPConnection
的子类如下信息
- (BOOL)isSecureServer
{
// Create an HTTPS server (all connections will be secured via SSL/TLS)
return YES;
}
/**
* This method is expected to returns an array appropriate for use in kCFStreamSSLCertificates SSL Settings.
* It should be an array of SecCertificateRefs except for the first element in the array, which is a SecIdentityRef.
**/
- (NSArray *)sslIdentityAndCertificates
{
SecIdentityRef identityRef = NULL;
SecCertificateRef certificateRef = NULL;
SecTrustRef trustRef = NULL;
NSString *thePath = [[NSBundle mainBundle] pathForResource:@"my" ofType:@"p12"];
NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
CFDataRef inPKCS12Data = (CFDataRef)CFBridgingRetain(PKCS12Data);
CFStringRef password = CFSTR("123");
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:(id)CFBridgingRelease(identityRef), (id)CFBridgingRelease(certificateRef), nil];
return result;
}