發表日期:2017-03 文章編輯:小燈 瀏覽次數:1961
快速適配直接看下面的示例代碼吧,概念有點多。。。
自己客戶端生成證書放在服務器上,可以自簽
服務器必須ca簽署,服務器生成,提供給我們
SSL/TLS協議運行機制概述
圖解SSL/TLS協議
HTTPS在建立Socket連接之前,需要進行握手。
1.客戶端向服務器端發送SSL協議版本號、加密算法種類、隨機數等信息。
2.服務端給客戶端返回SSL協議版本號、加密算法種類、隨機數等信息,同時也返回服務器端的證書,即公鑰證書。
3.客戶端使用服務端返回的信息驗證服務器的合法性,包括
4.客戶端向服務端發送自己所能支持的對稱加密方案,供服務器端進行選擇。
5.服務器端在客戶端提供的加密方案中選擇加密程度最高的加密方式。
6.服務器將選擇好的加密方案通過明文方式返回給客戶端。
7.客戶端接收到服務器端返回的加密方式后,使用該加密方式生成產生隨機碼,用作通信過程中對稱加密的秘鑰,使用服務器端返回的公鑰進行加密,將加密后的隨機碼發送至服務器。
8.服務器收到客戶端返回的加密信息后,使用自己的私鑰進行解密,獲取對稱加密秘鑰。
9.在接下來的會話中,服務器和客戶端將會使用該密碼進行對稱加密,保證通信過程中信息的安全。
單向認證:保證server是真的,通道是安全的(對稱密鑰);
雙向認證:保證client和server是真的,通道是安全的(對稱密鑰);
為了便于更好的認識和理解SSL協議,這里著重介紹SSL協議的握手協議。SSL協議既用到了公鑰加密技術又用到了對稱加密技術,對稱加密技術雖然比公鑰加密技術的速度快,可是公鑰加密技術提供了更好的身份認證技術。SSL的握手協議非常有效的讓客戶和服務器之間完成相互之間的身份認證。
1.客戶的瀏覽器向服務器傳遞客戶端SSL協議的版本號,加密算法的種類,產生的隨機數,以及其他服務器和客戶端之間通訊所需要的各種信息。
2.服務器向客戶端傳送SSL協議的版本號,加密算法的種類,隨機數以及其他相關信息,同時服務器還將向客戶端傳送自己的證書。
3.客戶利用服務器傳過來的信息驗證服務器的合法性,服務器的合法性包括
如果合法性驗證沒有通過,通訊將斷開,如果合法性驗證通過,將繼續進行第四步。
4.用戶端隨機產生一個用于后面通訊的“對稱密碼”,然后用服務器的公鑰(服務器的公鑰從步驟2終端服務器的證書中獲得)對其加密,然后將加密后的“預主密碼”傳給服務器。
5.如果服務器要求客戶的身份認證(在握手過程中為可選),用戶可以建立一個隨機數然后對其進行數據簽名,將這個含有簽名的隨機數和客戶自己的證書以及加密過的“預主密碼”一起傳給服務器。
6.如果服務器要求客戶的身份認證,服務器必須檢驗客戶證書和簽名隨機數的合法性,具體的合法性驗證過程包括:
檢驗如果沒有通過,通訊立刻中斷;如果驗證通過,服務器將用自己的私鑰解開加密的“預主密碼”,然后執行一系列步驟來產生主通訊密碼(客戶端也將通過同樣的方法產生相同的主通訊密碼)。
7.服務器和客戶端用相同的主密碼即“通話密碼”,一個對稱密鑰用于SSL協議的安全數據通訊的加解密通訊。同時在SSL通訊過程中還要完成數據通訊的完整性,防止數據通訊中的任何變化。
8.客戶端向服務器端發出信息,指明后面的數據通訊將使用步驟7中的主密碼為對稱密鑰,同時通知服務器客戶端的握手過程結束。
9.服務器向客戶端發出信息,指明后面的數據通訊將使用的步驟7中的主密碼為對稱密鑰,同時通知客戶端服務器端的握手過程結束。
10.SSL的握手部分結束,SSL安全通道的數據通訊開始,客戶和服務器開始使用相同的對稱密鑰進行數據通訊,同時進行通訊完整性的檢驗。
1.瀏覽器發送一個連接請求給安全服務器。
2.服務器將自己的證書,以及同證書相關的信息發送給客戶瀏覽器。
3.客戶瀏覽器檢查服務器送過來的證書是否是由自己信賴的CA中心所簽發的。如果是,就繼續執行協議;如果不是,客戶瀏覽器就給客戶一個警告消息:警告客戶這個證書不是可信賴的,詢問客戶是否需要繼續。
4.接著客戶瀏覽器比較證書里的消息,例如域名和公鑰,與服務器剛剛發送的相關消息是否一致,如果是一致的,客戶瀏覽器認可這個服務器合法身份。
5.服務器要求客戶發送客戶自己的證書。收到后,服務器驗證客戶的證書,如果沒有通過驗證,拒絕連接;如果通過驗證,服務器獲得用戶的公鑰。
6.客戶瀏覽器告訴服務器自己所能夠支持的通訊對稱密碼方案。
7.服務器從客戶發送過來的密碼方案中,選擇一種加密程度最高的密碼方案,用客戶的公鑰加過密后通知瀏覽器。
8.瀏覽器針對這個密碼方案,選擇一個通話密鑰,接著用服務器的公鑰加過密后發送給服務器。
9.服務器接收到瀏覽器送過來的消息,用自己的私鑰解密,獲得通話密鑰。
10.服務器、瀏覽器接下來的通訊都是用對稱密碼方案,對稱密鑰是加過密的。
上面所述的是雙向認證 SSL 協議的具體通訊過程,這種情況要求服務器和用戶雙方都有證書。單向認證 SSL 協議不需要客戶擁有 CA 證書,具體的過程相對于上面的步驟,只需將服務器端驗證客戶證書的過程去掉,以及在協商對稱密碼方案,對稱通話密鑰時,服務器發送給客戶的是沒有加過密的 (這并不影響 SSL 過程的安全性)密碼方案。 這樣,雙方具體的通訊內容,就是加過密的數據,如果有第三方攻擊,獲得的只是加密的數據,第三方要獲得有用的信息,就需要對加密的數據進行解密,這時候的 安全就依賴于密碼方案的安全。而幸運的是,目前所用的密碼方案,只要通訊密鑰長度足夠的長,就足夠的安全。這也是我們強調要求使用 128 位加密通訊的原因。
雙向認證和單向認證原理基本差不多,只是除了客戶端需要認證服務端以外,增加了服務器端對客戶端的認證。
單向認證只要求站點部署了SSL證書就行,任何用戶都可以去訪問(IP被限制除外等),只是服務器端提供了身份認證。而雙向認證則是需要服務端需要客戶端提供身份認證,只能是服務端允許的客戶能去訪問,安全性相對要高一些。
一般Web應用都是采用單向認證的,原因很簡單,用戶數目廣泛,且無需做在通訊層做用戶身份驗證,一般都在應用邏輯成來保護用戶的合法登入。但如果是企業對應對接,情況就不一樣,可能會要求對客戶端做身份驗證。這時就需要做雙向認證。
與單向認證的區別就是產生的是二分之一的對稱密鑰。
即對稱密鑰是client與server各自產生一半。
HTTPS = HTTP + SSL/TLS + TCP
TLS 是SSL新的別稱
也就是說 TLS 1.0 = SSL 3.1
常用的是下面這些
SSL 2.0
SSL 3.0
TLS 1.0 (SSL 3.1)
TLS 1.1 (SSL 3.1)
TLS 1.2 (SSL 3.1)
使用明文傳播,帶來了三大風險
竊聽風險(eavesdropping):第三方可以獲知通信內容。
篡改風險(tampering):第三方可以修改通信內容。
冒充風險(pretending):第三方可以冒充他人身份參與通信。
SSL/TLS協議是為了解決這三大風險而設計的,希望達到:
所有信息都是加密傳播,第三方無法竊聽。
具有校驗機制,一旦被篡改,通信雙方會立刻發現。
配備身份證書,防止身份被冒充。
蘋果ATS安全設置的要求
ATS默認的安全要求:
不滿足以上條件,ATS會拒絕連接。
方案一:讓公司的服務端升級使用TLS 1.2
方案二:雖Apple不建議,但可通過在 Info.plist 中聲明,倒退回不安全的網絡請求依然能讓App訪問指定http,甚至任意的http。
申請一個SSL證書
SSL證書按驗證的類別可分:
DV SSL證書(域名驗證型):只驗證域名所有權,適合個人網站、博客等站點使用;
OV SSL證書(企業驗證型):驗證網站所屬單位身份,適合企業級用戶使用;
EV SSL證書(擴展驗證型):擴展驗證網站所屬單位身份,這種證書在瀏覽器中會顯示醒目的綠色地址欄,可信度最高,適合需要用戶高度信任的企業級用戶使用。
注:AFNetworking 3.0以上
首先向后臺拿到證書(jks格式/Mac:.cer格式) ,或者你可以打開請求的完整鏈接 在Mac上下載該證書 (導入Xcode工程)
可以去騰訊云申請免費的SSL證書
檢測接口是否滿足蘋果的ATS要求,有以下兩種方法:
1.騰訊云提供的檢測頁面檢測
https://www.qcloud.com/product/tools
2.終端輸入 nsurl --ats-diagnostics --verbose 你的接口地址
關于iOS9中的ATS相關說明及適配
+ (AFSecurityPolicy *)customSecurityPolicy { // 先導入證書,在這加證書,一般情況適用于單項認證 // 證書的路徑 NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"xxx" ofType:@"cer"];NSData *cerData = [NSData dataWithContentsOfFile:cerPath];if (cerData == nil) { return nil; } NSSet *setData = [NSSet setWithObject:cerData]; //AFSSLPinningModeCertificate 使用證書驗證模式 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 = NO;[securityPolicy setPinnedCertificates:setData];return securityPolicy; }
然后在相應位置加入
[manager setSecurityPolicy:[self customSecurityPolicy]];
AFNetworking定義了三種SSLpinningmode:
AFSSLPinningModeNone: 代表客戶端無條件地信任服務器端返回的證書
AFSSLPinningModePublicKey : 代表客戶端會將服務器端返回的證書與本地保存的證書PublicKey的部分進行校驗;如果正確,才繼續進行。
AFSSLPinningModeCertificate: 代表客戶端會將服務器端返回的證書和本地保存的證書中的所有內容,包括PublicKey和證書部分,全部進行校驗;如果正確,才繼續進行。
http://blog.csdn.net/guobing19871024/article/details/53841373
http://blog.csdn.net/jerryvon/article/details/8548802
//校驗證書 + (void)checkCredential:(AFURLSessionManager *)manager { [manager setSessionDidBecomeInvalidBlock:^(NSURLSession * _Nonnull session, NSError * _Nonnull error) { }]; __weak typeof(manager)weakManager = manager; [manager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession*session, NSURLAuthenticationChallenge *challenge, NSURLCredential *__autoreleasing*_credential) { NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling; __autoreleasing NSURLCredential *credential =nil; NSLog(@"authenticationMethod=%@",challenge.protectionSpace.authenticationMethod); //判斷是核驗客戶端證書還是服務器證書 if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { // 基于客戶端的安全策略來決定是否信任該服務器,不信任的話,也就沒必要響應挑戰 if([weakManager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) { // 創建挑戰證書(注:挑戰方式為UseCredential和PerformDefaultHandling都需要新建挑戰證書) NSLog(@"serverTrust=%@",challenge.protectionSpace.serverTrust); credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; // 確定挑戰的方式 if (credential) { //證書挑戰設計policy,none,則跑到這里 disposition = NSURLSessionAuthChallengeUseCredential; } else { disposition = NSURLSessionAuthChallengePerformDefaultHandling; } } else { disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge; } } else { // client authentication SecIdentityRef identity = NULL; SecTrustRef trust = NULL; NSString *p12 = [[NSBundle mainBundle] pathForResource:@"xxx"ofType:@"p12"]; NSFileManager *fileManager =[NSFileManager defaultManager];if(![fileManager fileExistsAtPath:p12]) { NSLog(@"client.p12:not exist"); } else { NSData *PKCS12Data = [NSData dataWithContentsOfFile:p12];if ([self extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data]) { SecCertificateRef certificate = NULL; SecIdentityCopyCertificate(identity, &certificate); const void*certs[] = {certificate}; CFArrayRef certArray =CFArrayCreate(kCFAllocatorDefault, certs,1,NULL); credential =[NSURLCredential credentialWithIdentity:identity certificates:(__bridgeNSArray*)certArray persistence:NSURLCredentialPersistencePermanent]; disposition =NSURLSessionAuthChallengeUseCredential; } } } *_credential = credential; return disposition; }]; }//讀取p12文件中的密碼 + (BOOL)extractIdentity:(SecIdentityRef*)outIdentity andTrust:(SecTrustRef *)outTrust fromPKCS12Data:(NSData *)inPKCS12Data { OSStatus securityError = errSecSuccess; //client certificate password NSDictionary *optionsDictionary = [NSDictionary dictionaryWithObject:@"123456" forKey:(__bridge id)kSecImportExportPassphrase];CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); securityError = SecPKCS12Import((__bridge CFDataRef)inPKCS12Data,(__bridge CFDictionaryRef)optionsDictionary,&items);if(securityError == 0) { CFDictionaryRef myIdentityAndTrust =CFArrayGetValueAtIndex(items,0); const void*tempIdentity =NULL; tempIdentity= CFDictionaryGetValue (myIdentityAndTrust,kSecImportItemIdentity); *outIdentity = (SecIdentityRef)tempIdentity; const void*tempTrust =NULL; tempTrust = CFDictionaryGetValue(myIdentityAndTrust,kSecImportItemTrust); *outTrust = (SecTrustRef)tempTrust; } else { NSLog(@"Failedwith error code %d",(int)securityError); return NO; } return YES; }
然后在相應位置加入
[manager setSecurityPolicy:[self customSecurityPolicy]]; [self checkCredential:manager];
http://www.cnblogs.com/lmfboke/p/6232656.html
http://oncenote.com/2014/10/21/Security-1-HTTPS/
http://www.jianshu.com/p/97745be81d64
SDWebImage繞過證書驗證去加載圖片
[imageView sd_setImageWithURL:[NSURL URLWithString:urlString] placeholderImage:self.placeholder options:SDWebImageAllowInvalidSSLCertificates];
http://www.jianshu.com/p/72bf60b5f94d
http://www.cnblogs.com/lmfboke/p/6232656.html
http://blog.csdn.net/iostiannan/article/details/53763082
http://www.wosign.com/faq/faq-ios-https.htm
http://www.cocoachina.com/ios/20150702/12384.html
http://www.wosign.com/news/ios-app-https.htm
http://www.cocoachina.com/ios/20161207/18308.html
http://edison0663.iteye.com/blog/996526
日期:2018-04 瀏覽次數:6990
日期:2017-02 瀏覽次數:3686
日期:2017-09 瀏覽次數:3963
日期:2017-12 瀏覽次數:3768
日期:2018-12 瀏覽次數:5108
日期:2016-12 瀏覽次數:4809
日期:2017-07 瀏覽次數:13872
日期:2017-12 瀏覽次數:3736
日期:2018-06 瀏覽次數:4486
日期:2018-05 瀏覽次數:4672
日期:2017-12 瀏覽次數:3767
日期:2017-06 瀏覽次數:4184
日期:2018-01 瀏覽次數:4174
日期:2016-12 瀏覽次數:4134
日期:2018-08 瀏覽次數:4618
日期:2017-12 瀏覽次數:3979
日期:2016-09 瀏覽次數:6733
日期:2018-07 瀏覽次數:3412
日期:2016-12 瀏覽次數:3448
日期:2018-10 瀏覽次數:3589
日期:2018-10 瀏覽次數:3703
日期:2018-09 瀏覽次數:3812
日期:2018-02 瀏覽次數:3824
日期:2015-05 瀏覽次數:3731
日期:2018-09 瀏覽次數:3511
日期:2018-06 瀏覽次數:3635
日期:2017-02 瀏覽次數:4079
日期:2018-02 瀏覽次數:4579
日期:2018-02 瀏覽次數:4441
日期:2016-12 瀏覽次數:3775
Copyright ? 2013-2018 Tadeng NetWork Technology Co., LTD. All Rights Reserved.