2016-06-13 21 views
0

私は困惑しています:私のアプリは、HTTPS用の自己署名証明書を使用するサーバーに接続する必要があり、クライアント側の認証が必要です。さらに悪いことに、私は実際にそのサーバーに接続するためのiOSメディアプレーヤーを必要とするので、私は手紙にAppleのinstructionこのために従っている:NSURLCredentialStorage setDefaultCredential:[NSURLSession sharedSession]のために動作しません

credential = [NSURLCredential credentialWithIdentity:identity certificates:certs persistence:NSURLCredentialPersistenceForSession]; 
NSURLProtectionSpace *space = [[NSURLProtectionSpace alloc] initWithHost:@"server.com" 
                    port:0 
                   protocol:NSURLProtectionSpaceHTTPS 
                    realm:nil 
                authenticationMethod:NSURLAuthenticationMethodClientCertificate]; 
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:space]; 

しかし、それだけでは動作しません。私は自分のNSURLSessionを設定し、URLSession使用している場合今

2016-06-13 08:22:37.767 TestiOSSSL[3172:870700] CFNetwork SSLHandshake failed (-9824 -> -9829) 
2016-06-13 08:22:37.793 TestiOSSSL[3172:870700] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9829) 
2016-06-13 08:22:37.815 TestiOSSSL[3172:870685] Done : Error Domain=NSURLErrorDomain Code=-1206 "The server “ server.com” requires a client certificate." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x13de519b0>, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9829, NSUnderlyingError=0x13de4f280 {Error Domain=kCFErrorDomainCFNetwork Code=-1206 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=1, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x13de519b0>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9829, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9829, kCFStreamPropertySSLPeerCertificates=<CFArray 0x13dda0a70 [0x1a0dc2150]>{type = immutable, count = 2, values = (
    0 : <cert(0x13dda4970) s: Server.com i: Localhost CA> 
    1 : <cert(0x13dda50d0) s: Localhost CA i: Localhost CA> 
)}}}, NSErrorPeerCertificateChainKey=<CFArray 0x13dda0a70 [0x1a0dc2150]>{type = immutable, count = 2, values = (
    0 : <cert(0x13dda4970) s: Server.com i: Localhost CA> 
    1 : <cert(0x13dda50d0) s: Localhost CA i: Localhost CA> 
)}, NSLocalizedDescription=The server “server.com” requires a client certificate., NSErrorFailingURLKey=https://server.com/, NSErrorFailingURLStringKey=https://server.com/, NSErrorClientCertificateStateKey=1} 

:didReceiveChallenge:completionHandlerを私が得るすべては、このエラーである

NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@"https://server.com"] 
             completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
              NSLog(@"Done : %@", error ? error : @"OK"); 
             }]; 

:だから私は、手動でサーバーに要求を実行しようとしました。コールバック:

NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; 
theSession = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil]; 
NSURLSessionDataTask *task = [theSession dataTaskWithURL:[NSURL URLWithString:@"https://server.com"] 
             completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
              NSLog(@"Done : %@", error ? error : @"OK"); 
             }]; 

、その後:

- (void)URLSession:(NSURLSession *)session 
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge 
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, 
          NSURLCredential *credential))completionHandler 
{ 
    NSLog(@"Asking for credential"); 
    NSURLCredential *conf = [session.configuration.URLCredentialStorage defaultCredentialForProtectionSpace:challenge.protectionSpace]; 
    completionHandler(NSURLSessionAuthChallengeUseCredential, conf); 
} 

[session.configuration.URLCredentialStorage defaultCredentialForProtectionSpace:challenge.protectionSpace]を使用していることに注目してください。これは、NSURLSessionのデフォルト実装が認証チャレンジを取得したときに行うものです。

これは、この特定の接続で機能します。これは、資格証明がOKであり、デフォルトの資格証明としてデフォルトNSURLCredentialStorageに正しく登録されていることを証明します。

しかし、didReceiveChallenge:コールバックの周りをヒンティングするソリューションは、メディアプレーヤーが使用しているNSURLSessionを制御できないため、いいです。

私はCustomHTTPProtocolハックを試しましたが、どちらもうまくいきません。

提案がありますか?私はSOのすべての同様の記事を見てきましたが、私はこれのための解決策を見つけることができません。このpostは本当に近いですが、受け入れられた答えは私にとって意味をなさないものであり、明らかにAppleのドキュメンテーションと矛盾しています。

答えて

0

デフォルトセッションとNSURLConnectionの間で多くの機能が共有されていますが、そのビットは明らかではありません。あなたは[NSURLSession sharedSession].configuration.URLCredentialStorageでそのメソッドを呼び出そうとしましたか?

別の可能性として、別のタスクでリクエストが発生している可能性があります。その場合は、別の共有セッションが必要になるため、試行中のリクエストを実行できないことがあります。そのような場合は、資格情報を自分自身でキーチェーンに保存し、他のプロセスがキーチェーンを共有して資格情報を適切に取得することを信頼する必要があります。

+0

提案していただきありがとうございます。はい、私はsharedSessionで呼び出すようにしましたが、喜びはありません。いずれにしても、iOS MediaPlayerが自分のプロセスで実行されていないため、共有された資格情報ストレージを使用することは決してできません。別のプロセスに完全に分離され、アプリケーションと画面を共有するだけです。実際に働いていた唯一の解決策は、サーバーとしてメディアプレーヤーに配置されたアプリケーションにHTTPプロキシをセットアップし、受信したリクエストを実際のサーバーに転送して、独自の接続で資格情報を処理することでした。 Clunky :-( –

+0

それはあなたがまだWebビューのものをやっている人にとっては問題です。もしあなたがまだAppleにバグを報告して、メディアプレーヤーに資格を与える方法を尋ねてください。何年もの間、繰り返し問題になってきました。私のウェブサイトの1つには、Safariの内蔵ビデオ再生が数年前に基本またはダイジェストの認証情報を渡すことができなかったという事実を回避するためのヒントがまだあります。私はバグを提出し、最終的にそれを修正しましたが、明らかにそれは彼らが多く考えている使用モデルではありません。認証が重要であることを知らせるバグを提出してください。 – dgatwood

関連する問題