2011-06-22 36 views
3

我試圖從iOS中的各種URL讀取證書。然而,我的代碼工作不正常 - 應該返回我需要的信息的數組總是返回null在iOS上閱讀證書問題

我錯過了什麼?

- (void)findCertificate:(NSString *)url 
{ 
    NSInputStream*input = [[NSInputStream inputStreamWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"https://store.writeitstudios.com"]]] retain]; 

    [input setDelegate:self]; 

    [input scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; 

    [input open]; 

    NSLog(@"Status: %i",[input streamStatus]); 
} 

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode 
{ 
    NSLog(@"handle Event: %i",eventCode); 

    if (eventCode == NSStreamStatusOpen) 
    { 
     NSArray *certificates = (NSArray*)CFReadStreamCopyProperty((CFReadStreamRef)aStream, kCFStreamPropertySSLPeerCertificates); 

     NSLog(@"Certs: %@",CFReadStreamCopyProperty((CFReadStreamRef)aStream, kCFStreamPropertySSLPeerCertificates)); 

     if ([certificates count] > 0) { 
      SecCertificateRef certificate = (SecCertificateRef)[certificates objectAtIndex:0]; 
      NSString *description = (NSString*)SecCertificateCopySubjectSummary(certificate); 
      NSData *data = (NSData *)SecCertificateCopyData(certificate); 
      NSLog(@"Description: %@",description); 
     } 
    } 
} 

是的,我知道我在泄漏記憶。這只是一個片段。

回答

9

讓我解釋一下,你在這裏做什麼,以及爲什麼這是錯的:

  1. 您加載的URL https://store.writeitstudios.com(即HTML)的內容同步到NSData(數據緩衝器)。請注意,您是加載任何證書(當然,技術上NSURL將在內部加載它們,但是這個代碼是最絕對不是把它們放入NSData
  2. 您正在打開的輸入流,並堅持的數據(位HTML,沒有證書!)。
  3. 您已實施NSStream的委託方法stream:handleEvent:並試圖讀取kCFStreamPropertySSLPeerCertificates屬性。這個屬性將是空的,因爲流只包含一點HTML數據,沒有別的。
  4. 您正在將空屬性轉換爲NSArray
  5. 循環未執行,因爲數組爲NULL

使用NSStream/CFStream對於手頭的任務不是必需的。並且絕對不必先通過NSURLConnection然後再通過NSStream

要獲取SSL服務器證書,堅持一個簡單的,異步NSURLConnection和使用它的委託方法來訪問證書:

// Method to begin the asynchronous download 

- (void)beginCertificateDownload:(NSURL *)url 
{ 
    NSURLRequest *request = [NSURLRequest requestWithURL:url]; 
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 

    [connection start]; 
} 

// NSURLConnection Delegate Methods 

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace 
{ 
    return [[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust]; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 
{ 
    // extract the certificates 
    SecTrustRef trustRef = [[challenge protectionSpace] serverTrust]; 
    CFIndex count = SecTrustGetCertificateCount(trustRef); 
    for (CFIndex i = 0; i < count; i++) { 
     SecCertificateRef certRef = SecTrustGetCertificateAtIndex(trustRef, i); 
     CFStringRef certSummary = SecCertificateCopySubjectSummary(certRef); 
     NSLog(@"%@", certSummary); 

     // do whatever you need with the certificates here 
     // don't forget to copy them if you need to keep them 
     // around beyond the scope of this method 
    } 

    // I'm assuming you're not interested in actually loading the contents of the URL, so cancel 
    [[challenge sender] cancelAuthenticationChallenge:challenge]; 

    // you'll also want to release the connection object at some point 
} 
+0

這個腳本非常適用於網站,如貝寶,但不返回https://store.writeitstudios.com的結果。這是否只承認最常見的證書頒發機構頒發的證書? – Pripyat

+0

它在我的網站上工作。你確定你使用的是https網址嗎?委託方法是否被調用? – puzzle

+0

確實調用了委託方法。它基本上只是調用didStartConnection和didFinishConnection。它適用於大多數網址,但出於某種原因不適用於該網址。 – Pripyat