前言
蘋果在iOS9中加入了ATS锦募,不清楚的同學(xué)點(diǎn)擊任意門ATS適配, 當(dāng)然這個其實(shí)也是蠻好的鲸郊,安全嘛榨汤,這篇文章的主題是講如何用CocoaHttpServer 實(shí)現(xiàn)https.
生成自簽名證書
到OpenSSL官網(wǎng)下載最新版本惶楼,解壓之后拷貝demoCA到你想要放的文件夾屁魏,當(dāng)然你也可以自己生成一個demoCA滔以,在app目錄中找到CA.sh,拷貝到你的目錄氓拼,執(zhí)行
sh ./CA.sh -newca
然后創(chuàng)建一個目錄
mkdir server
創(chuàng)建一個私鑰
openssl genrsa -out server/server-key.pem 2048
創(chuàng)建證書請求
openssl req -new -out server/server-req.csr -key server/server-key.pem
然后會需要填寫一系列信息
Country Name (2 letter code) [AU]:cn
State or Province Name (full name) [Some-State]:fujian
Locality Name (eg, city) []:xiamen
Organization Name (eg, company) [Internet Widgits Pty Ltd]:test
Organizational Unit Name (eg, section) []:test
Common Name (eg, YOUR name) []:127.0.0.1 注釋:一定要寫服務(wù)器所在的ip地址
Email Address []:sky
Common Name 這一項必須填 localhost 或者 127.0.0.1 你画,如果填寫127.0.0.1,那么頁面中請求只能使用https://127.0.0.1:60000 而不能使用 https://localhost:60000桃漾,反之相同坏匪。
自簽署證書
openssl x509 -req -in server/server-req.csr -out server/server-cert.pem -signkey server/server-key.pem -CA demoCA/cacert.pem -CAkey demoCA/private/cakey.pem -CAcreateserial -days 3650
將證書導(dǎo)出成瀏覽器支持的.p12格式,記得導(dǎo)出密碼
openssl pkcs12 -export -clcerts -in server/server-cert.pem -inkey server/server-key.pem -out server/server.p12
自簽名證書生成完成撬统。
工程配置
將生成的p12放到工程目錄下面适滓,同時新建一個 MyHttpConnection 繼承于 HttpConnection ,重載 - (BOOL)isSecureServer 方法及 sslIdentityAndCertificates 方法
- (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:@"TestCertificate" 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;
}
- (NSObject<HTTPResponse> *)httpResponseForMethod:(NSString *)method URI:(NSString *)path
{
// do something
return [super httpResponseForMethod:method URI:path];
}
同時在啟動 HTTPServer(調(diào)用 startServer )之前恋追,使用 setConnectionClass 方法將 HTTPConnecdtion 替換為 MyHTTPConnection
[_httpServer setConnectionClass:[MyHTTPConnection class]];
WKWebView代理配置
WKWebView需要在WKNavagationDelegate方法中允許使用凭迹,這個方法和AFNetworking處理方法很相似罚屋,當(dāng)然你如果是用safari打開對應(yīng)的鏈接的話,就得safari允許自簽名的證書嗅绸。
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
NSURLCredential *card = [[NSURLCredential alloc] initWithTrust:challenge.protectionSpace.serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential, card);
}
}
ATS設(shè)置
為App Transport Security Settings
添加Allow Arbitrary Loads in Web Content
設(shè)置為YES
結(jié)束
附上我自己寫的小demo, 打完收工F⒚汀!鱼鸠!