關于HTTPS的那些事

iOS中集成HTTPS

證書是自簽名的HTTPS證書,如果是CA認證的就不會有下面的事情了。項目組最后到阿里云去申請免費試用一年的HTTPS證書。下面的純屬是為了紀念曾經折騰過的問題:

NSURLSession驗證HTTPS

首先要成為NSURLSession的代理
<pre>
NSString *urlString = @"https://xxxx";
NSURL *myUrl = [NSURL URLWithString:urlString];

NSMutableURLRequest *myRequest = [NSMutableURLRequest requestWithURL:myUrl cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10.0f];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];

NSURLSessionDataTask *task = [session dataTaskWithRequest:myRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
}];
[task resume];

</pre>
然后實現下面的代理方法
<pre>
/*

  • 代理方法 NSURLSessionDelegate
    */
  • (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
    NSLog(@"證書認證開始..");
    //先導入證書
    NSString * cerPath = [[NSBundle mainBundle] pathForResource:@"你的證書名字" ofType:@"cer"]; //證書的路徑
    NSData * cerData = [NSData dataWithContentsOfFile:cerPath];
    SecCertificateRef certificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(cerData));
    NSArray * trustedCertificates = @[CFBridgingRelease(certificate)];
    //1)獲取trust object
    SecTrustRef trust = challenge.protectionSpace.serverTrust;
    SecTrustResultType result;
    //注意:這里將之前導入的證書設置成下面驗證的Trust Object的anchor certificate
    SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)trustedCertificates);
    //2)SecTrustEvaluate會查找前面SecTrustSetAnchorCertificates設置的證書或者系統默認提供的證書,對trust進行驗證
    OSStatus status = SecTrustEvaluate(trust, &result);
    if (status == errSecSuccess &&
    (result == kSecTrustResultProceed ||
    result == kSecTrustResultUnspecified)) {
    NSLog(@"驗證成功..");
    //3)驗證成功,生成NSURLCredential憑證cred,告知challenge的sender使用這個憑證來繼續連接
    NSURLCredential *cred = [NSURLCredential credentialForTrust:trust];
    [challenge.sender useCredential:cred forAuthenticationChallenge:challenge];completionHandler(NSURLSessionAuthChallengeUseCredential,cred);
    } else {
    NSLog(@"驗證失敗..");
    [challenge.sender cancelAuthenticationChallenge:challenge];
    }
    }
    </pre>

AFNetWorking

我們先封裝出來一個Post方法,設置AFN的setSecurityPolicy方法
<pre>
/**

  • pots方法
    */
  • (void)post:(NSString *)url params:(NSDictionary *)params success:(void (^)(id))success failure:(void (^)(NSError *))failure
    {
    // 1.獲得請求管理者
    AFHTTPSessionManager *mgr = [[AFHTTPSessionManager manager] initWithBaseURL:[NSURL URLWithString:BaseUrl]];
    // 2.申明返回的結果是text/html類型

    mgr.responseSerializer = [AFHTTPResponseSerializer serializer];

    // 加上這行代碼,https ssl 驗證。
    [mgr setSecurityPolicy:[self customSecurityPolicy]];

    // 3.發送POST請求
    [mgr POST:url parameters:params progress:nil success:^(NSURLSessionDataTask * task, id responseObject) {
    if (success) {
    success(responseObject);
    }
    } failure:^(NSURLSessionDataTask * task, NSError * error) {
    if (failure) {
    failure(error);
    }
    }];
    }
    </pre>

自定義的customSecurityPolicy方法:
<pre>

  • (AFSecurityPolicy*)customSecurityPolicy
    {
    // /先導入證書
    NSString *cerPath = [[NSBundle mainBundle] pathForResource:CertName ofType:@"cer"];//證書的路徑
    NSData *certData = [NSData dataWithContentsOfFile:cerPath];

    // 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;

    NSSet *set = [[NSSet alloc] initWithObjects:certData, nil];

    securityPolicy.pinnedCertificates = set;

    return securityPolicy;
    }
    </pre>

完成!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 這篇文章是我一邊學習證書驗證一邊記錄的內容,稍微整理了下,共扯了三部分內容: HTTPS 簡要原理;數字證書的內容...
    左邊飛來一只狗閱讀 3,343評論 2 5
  • iOS安全系列之一:HTTPS 2014-10-21 如何打造一個安全的App?這是每一個移動開發者必須面對的問題...
    不作不會死閱讀 765評論 0 4
  • 原文地址:iOS安全系列之一:HTTPS 如何打造一個安全的App?這是每一個移動開發者必須面對的問題。在移動Ap...
    violafa閱讀 886評論 0 2
  • 一、作用 不使用SSL/TLS的HTTP通信,就是不加密的通信。所有信息明文傳播,帶來了三大風險。 (1)竊聽風險...
    XLsn0w閱讀 10,745評論 2 44
  • HTTPS其實HTTPS從最終的數據解析的角度,與HTTP沒有任何的區別,HTTPS就是將HTTP協議數據包放到S...
    七維樹閱讀 613評論 0 2