HTTPS 證書處理 objective-c實現

前一篇文章用c#處理了證書,這次就使用oc來試一下,其實基本原理累似,一般都是自己覆蓋幾個函數,然後自己處理證書相關的東西。

自己創建一個類,如:

@interface MyURLConnection : NSObject<NSURLConnectionDelegate, NSURLConnectionDataDelegate>

- (void) sendPostRequest: (NSURL*)url postData: (NSData*)postData;

@end
我比較喜歡把一些不需要對外公開的成員放在extension裏面,省的別人看見。
@interface MyURLConnection()
{
    NSURLConnection*    _conn;
    NSMutableData*      _receivedData;
    BOOL                _success;
}

@end

然後實現sendPostRequest函數:

-(void) sendPostRequest:(NSURL *)url postData:(NSData *)postData
{
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:url];
    [request setHTTPMethod:@"POST"];
    NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[postData length]];
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
    [request setValue:@"text/plain, charset=UTF-8" forHTTPHeaderField:@"Content-Type"];
    
    [request setHTTPBody:postData];
    
//    NSLog(@"all headers: %@", request.allHTTPHeaderFields);
    
    _conn = [NSURLConnection connectionWithRequest:request delegate:self];
    
    [_conn start];
    
    _receivedData = nil;
    _success = NO;
}
實現NSURLConnection的幾個delegate函數:(上面的NSURLConnection操作是異步的)

- (void)connection: (NSURLConnection*) connection didReceiveResponse:(NSURLResponse *)response
{
    if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
        NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
        if (statusCode != 200) {
            NSLog(@"%s failed status code %ld", __FUNCTION__, (long)statusCode);
            _success = NO;
        }
        else
        {
            _success = YES;
        }
    }
    
    _receivedData = nil;
}

- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    if (!_receivedData) {
        _receivedData = [[NSMutableData alloc] initWithData:data];
    }
    else
    {
        [_receivedData appendData:data];
    }
}

- (void) connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSString* data = [[NSString alloc] initWithData:_receivedData encoding:NSUTF8StringEncoding];
//    NSLog(@"NXURlConnection, finished loading: %@", data);
    
    NSError* err = nil;
    if (!_success) {
        err = [[NSError alloc] initWithDomain:@"https access failed" code:1 userInfo:nil];
    }
    else
    {
        // success
    }
}


- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    _success = NO;
    NSLog(@"NXURLConnection error: %@", [error localizedDescription]);
}

- (void) connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    NSLog(@"willSendRequestForAuthentiationChallenge: %@", challenge.protectionSpace.authenticationMethod);
    if ([challenge.protectionSpace.authenticationMethod isEqualToString: NSURLAuthenticationMethodServerTrust]) {
        NSLog(@"cert host: %@", challenge.protectionSpace.host);
   
        NSURLCredential* cred = [NSURLCredential credentialForTrust:[[challenge protectionSpace] serverTrust]];
        [[challenge sender] useCredential: cred forAuthenticationChallenge:challenge];
    }
}

前面幾個函數從字面意思就可以知道是對訪問的一些處理,比如成功失敗什麼的。關鍵是最後一個函數。

這個函數裏面可以處理證書相關的東西,比如獲取證書信息等,上面的例子是無論什麼證書,都通過。當然我們也可以根據具體的證書信息做一些判斷,比如不是公司自己的證書,就取消操作什麼的。

調用:

    MyURLConnection* conn = [[MyURLConnection alloc]init];
    
    [conn sendPostRequest:@"https://xxxxx" postData:@"test"];

這樣,就算測試站點的證書是自己創建的測試證書,也可以成功訪問到數據了。



發佈了140 篇原創文章 · 獲贊 49 · 訪問量 64萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章