- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust
forDomain:(NSString *)domain
{
//當使用自建證書驗證域名時,需要使用AFSSLPinningModePublicKey或者AFSSLPinningModeCertificate
if (domain && self.allowInvalidCertificates && self.validatesDomainName && (self.SSLPinningMode == AFSSLPinningModeNone || [self.pinnedCertificates count] == 0)) {
// https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/OverridingSSLChainValidationCorrectly.html
// According to the docs, you should only trust your provided certs for evaluation.
// Pinned certificates are added to the trust. Without pinned certificates,
// there is nothing to evaluate against.
//
// From Apple Docs:
// "Do not implicitly trust self-signed certificates as anchors (kSecTrustOptionImplicitAnchors).
// Instead, add your own (self-signed) CA certificate to the list of trusted anchors."
NSLog(@"In order to validate a domain name for self signed certificates, you MUST use pinning.");
return NO;
}
//需要驗證域名時,需要添加一個驗證域名的策略
NSMutableArray *policies = [NSMutableArray array];
if (self.validatesDomainName) {
[policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];
} else {
[policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()];
}
//設置驗證的策略,可以是多個
SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);
if (self.SSLPinningMode == AFSSLPinningModeNone) {
return self.allowInvalidCertificates || AFServerTrustIsValid(serverTrust);
} else if (!AFServerTrustIsValid(serverTrust) && !self.allowInvalidCertificates) {
return NO;
}
//獲取服務器證書的內容
switch (self.SSLPinningMode) {
case AFSSLPinningModeNone:
default:
return NO;
case AFSSLPinningModeCertificate: {
//AFSSLPinningModeCertificate是直接將本地的證書設置為信任的根證書,然后來進行判斷,并且比較本地證書的內容和服務器證書內容是否相同,如果有一個相同則返回YES
NSMutableArray *pinnedCertificates = [NSMutableArray array];
for (NSData *certificateData in self.pinnedCertificates) {
[pinnedCertificates addObject:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData)];
}
//設置本地的證書為服務器的根證書
SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCertificates);
//通過本地的證書來判斷服務器證書是否可信,不可信,則驗證不通過
if (!AFServerTrustIsValid(serverTrust)) {
return NO;
}
// obtain the chain after being validated, which *should* contain the pinned certificate in the last position (if it's the Root CA)
NSArray *serverCertificates = AFCertificateTrustChainForServerTrust(serverTrust);
//客戶端是否完全包含服務端證書
for (NSData *trustChainCertificate in [serverCertificates reverseObjectEnumerator]) {
if ([self.pinnedCertificates containsObject:trustChainCertificate]) {
return YES;
}
}
return NO;
}
case AFSSLPinningModePublicKey: {
//AFSSLPinningModePublicKey是通過比較證書當中公鑰(PublicKey)部分來進行驗證,通過SecTrustCopyPublicKey方法獲取本地證書和服務器證書,然后進行比較,如果有一個相同,則通過驗證
NSUInteger trustedPublicKeyCount = 0;
//服務端證書
NSArray *publicKeys = AFPublicKeyTrustChainForServerTrust(serverTrust);
//判斷服務器證書的公鑰與本地的證書公鑰是否相同,相同則客戶端認證通過
for (id trustChainPublicKey in publicKeys) {
//遍歷客戶端證書
for (id pinnedPublicKey in self.pinnedPublicKeys) {
//對比兩者的證書是否相同
if (AFSecKeyIsEqualToKey((__bridge SecKeyRef)trustChainPublicKey, (__bridge SecKeyRef)pinnedPublicKey)) {
trustedPublicKeyCount += 1;
}
}
}
return trustedPublicKeyCount > 0;
}
}
return NO;
}
帶你讀懂AF3.0證書驗證核心函數
最后編輯于 :
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
- 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
- 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
- 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
推薦閱讀更多精彩內容
- 在Xcode7.0之后,蘋果廢棄了NSURLConnection方法,數據請求使用NSURLSession,作為網...
- 1、修改AFNetworking中修改源碼,在AFSecurityPolicy.m注釋掉這幾句 或者可以添加一個宏...
- 馬上就2017年了,據說元旦apple就強制HTTPS了,就像之前強制IPV6一樣任性,好方~~~不到萬不得已,項...
- 設置AFN請求管理者的時候添加httpsssl驗證。 //1.獲得請求管理者 AFHTTPSessionManag...