https 安全驗證問題,https驗證

來源:互聯網
上載者:User

https 安全驗證問題,https驗證

最近為了滿足蘋果的 https 要求, 經過努力終於寫出了方法

驗證 SSL 憑證是否滿足 ATS 要求

nscurl --ats-diagnostics --verbose https://你的網域名稱

PASS 符合要求

輸出滿足 ATS 的認證

openssl s_client -connect 你的網域名稱:443 </dev/null 2>/dev/null | openssl x509 -outform DER > https.cer

1. 針對 AFNetWorking (2.6.0之前的版本)

AFSecurityPolicy分三種驗證模式:

AFSSLPinningModeNone

這個模式表示不做SSL pinning,
只跟瀏覽器一樣在系統的信任機構列表裡驗證服務端返回的認證。若認證是信任機構簽發的就會通過,若是自己伺服器產生的認證就不會通過。

AFSSLPinningModeCertificate

這個模式表示用認證綁定方式驗證認證,需要用戶端儲存有服務端的認證拷貝,這裡驗證分兩步,第一步驗證認證的網域名稱有效期間等資訊,第二步是對比服務端返回的認證跟用戶端返回的是否一致。 

AFSSLPinningModePublicKey

這個模式同樣是用認證綁定方式驗證,用戶端要有服務端的認證拷貝,
只是驗證時只驗證認證裡的公開金鑰,不驗證認證的有效期間等資訊。只要公開金鑰是正確的,就能保證通訊不會被竊聽,因為中間人沒有私密金鑰,無法解開通過公開金鑰加密的資料。

 

// 正對是 app 新人的機構發布的 SSL 憑證

AFSecurityPolicy * securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];

//allowInvalidCertificates 是否允許無效認證(也就是自建的認證),預設為NO //如果是需要驗證自建認證,需要設定為YES

securityPolicy.allowInvalidCertificates = YES;

//validatesDomainName 是否需要驗證網域名稱,預設為YES;

//假如認證的網域名稱與你請求的網域名稱不一致,需把該項設定為NO;如設成NO的話,即伺服器使用其他可信任機構頒發的認證,也可以建立串連,這個非常危險,建議開啟。

//置為NO,主要用於這種情況:用戶端請求的是子網域名稱,而認證上的是另外一個網域名稱。因為SSL認證上的網域名稱是獨立的,假如認證上註冊的網域名稱是www.google.com,那麼mail.google.com是無法驗證通過的;當然,有錢可以註冊萬用字元的網域名稱*.google.com,但這個還是比較貴的。

//如置為NO,建議自己添加對應網域名稱的校正邏輯。

securityPolicy.validatesDomainName = YES;

//validatesCertificateChain 是否驗證整個憑證鏈結,預設為YES

//設定為YES,會將伺服器返回的Trust Object上的憑證鏈結與本地匯入的認證進行對比,這就意味著,假如你的憑證鏈結是這樣的:

//GeoTrust Global CA // Google Internet Authority G2

// *.google.com //那麼,除了匯入*.google.com之外,還需要匯入憑證鏈結上所有的CA認證(GeoTrust Global CA, Google Internet Authority G2);

//如是自建認證的時候,可以設定為YES,增強安全性;假如是信任的CA所簽發的認證,則建議關閉該驗證,因為整個憑證鏈結一一比對是完全沒有必要(請查看原始碼);

securityPolicy.validatesCertificateChain = NO;  // 2.6.0之前不需要, 之後需要

requestOperationManager.securityPolicy = securityPolicy;

// 如實自建的認證

還需要把認證匯入本地工程中, 並天添加以下代碼

NSData *cerData = [self getSSLCerByCerName:@"本地SSL認證的名字 "];
[securityPolicy setPinnedCertificates:@[cerData]];

// 擷取 SSL 憑證

+ (NSData *)getSSLCerByCerName:(NSString *)cerName {
NSString *cerPath = [[NSBundle mainBundle] pathForResource:cerName
ofType:@"cer"];
NSData *certData = [NSData dataWithContentsOfFile:cerPath];
return certData;
}

 

2. 針對 NSURLConnection

驗證認證的API

相關的Api在Security Framework中,驗證流程如下:

1). 第一步,先擷取需要驗證的信任物件(Trust Object)。這個Trust Object在不同的應用情境下擷取的方式都不一樣,對於NSURLConnection來說,是從delegate方法-connection:willSendRequestForAuthenticationChallenge:回調回來的參數challenge中擷取([challenge.protectionSpace serverTrust])。

2). 使用系統預設驗證方式驗證Trust Object。SecTrustEvaluate會根據Trust Object的驗證策略,一級一級往上,驗證憑證鏈結上每一級數位簽章的有效性(上一部分有講解),從而評估認證的有效性。

3). 如第二步驗證通過了,一般的安全要求下,就可以直接驗證通過,進入到下一步:使用Trust Object產生一份憑證([NSURLCredential credentialForTrust:serverTrust]),傳入challenge的sender中([challenge.sender useCredential:cred forAuthenticationChallenge:challenge])處理,建立串連。

4). 假如有更強的安全要求,可以繼續對Trust Object進行更嚴格的驗證。常用的方式是在本地匯入認證,驗證Trust Object與匯入的認證是否匹配。更多的方法可以查看Enforcing Stricter Server Trust Evaluation,這一部分在講解AFNetworking源碼中會講解到。

5). 假如驗證失敗,取消此次Challenge-Response Authentication驗證流程,拒絕串連請求。

ps: 假如是自建認證的,則不使用第二步系統預設的驗證方式,因為自建認證的根CA的數位簽章未在作業系統的信任清單中。

iOS授權驗證的API和流程大概瞭解了,下面,我們看看在NSURLConnection中的代碼實現:

 

// NSURLConnection Https 安全驗證問題
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace{
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
// 針對的是自建認證, 未受安全機構信任
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
static CFArrayRef certs;
if (!certs) {
NSData*certData =[NSData dataWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:@"本地工程中的SSL認證的名字" ofType:@"cer"]];
SecCertificateRef rootcert
=SecCertificateCreateWithData(kCFAllocatorDefault,CFBridgingRetain(certData));
const void *array[1] = { rootcert };
certs = CFArrayCreate(NULL, array, 1, &kCFTypeArrayCallBacks);
CFRelease(rootcert);
}

SecTrustRef trust = [[challenge protectionSpace] serverTrust];
// 針對一個認證對應多個網域名稱, 無需驗證網域名稱
NSMutableArray *policies = [NSMutableArray array];
// BasicX509 不驗證網域名稱是否相同
SecPolicyRef policy = SecPolicyCreateBasicX509();
[policies addObject:(__bridge_transfer id)policy];
SecTrustSetPolicies(trust, (__bridge CFArrayRef)policies);
int err;
SecTrustResultType trustResult = 0;
err = SecTrustSetAnchorCertificates(trust, certs);
if (err == noErr) {
err = SecTrustEvaluate(trust,&trustResult);
}
CFRelease(trust);
// kSecTrustResultUnspecified: 系統隱式地信任這個認證
// kSecTrustResultProceed: 使用者加入自己的信任錨點,顯式地告訴系統這個認證是值得信任的
BOOL trusted = (err == noErr)
&& ((trustResult == kSecTrustResultProceed)
|| (trustResult == kSecTrustResultUnspecified));
if (trusted) {
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]
forAuthenticationChallenge:challenge];
}else{
[challenge.sender cancelAuthenticationChallenge:challenge];
}
}


// SSL 憑證是經過信任的機構授權的, 不用再把認證存放在本地
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
//1)擷取trust object
SecTrustRef trust = challenge.protectionSpace.serverTrust;
SecTrustResultType result;

// 針對一個認證對應多個網域名稱, 無需驗證網域名稱
NSMutableArray *policies = [NSMutableArray array];
// BasicX509 不驗證網域名稱是否相同
SecPolicyRef policy = SecPolicyCreateBasicX509();
[policies addObject:(__bridge_transfer id)policy];
SecTrustSetPolicies(trust, (__bridge CFArrayRef)policies);

//2)SecTrustEvaluate對trust進行驗證
OSStatus status = SecTrustEvaluate(trust, &result);
if (status == errSecSuccess &&
(result == kSecTrustResultProceed ||
result == kSecTrustResultUnspecified)) {
//3)驗證成功,產生NSURLCredential憑證cred,告知challenge的sender使用這個憑證來繼續串連
NSURLCredential *cred = [NSURLCredential credentialForTrust:trust];
[challenge.sender useCredential:cred forAuthenticationChallenge:challenge];

} else {
//5)驗證失敗,取消這次驗證流程
[challenge.sender cancelAuthenticationChallenge:challenge];
}
}

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.