2017-11-06 11 views
0

私のサーバーは自己署名入りのSSL証明書を使用しています。そして、私が何をしても、iOSはそれらを受け入れたくありません。これは私のコードです:NSURLSessionAuthChallengeUseCredentialは役に立ちません。 iOSを自分のサーバーに信頼させる方法

- (void)URLSession:(NSURLSession *)session 
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge 
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, 
         NSURLCredential *credential))completionHandler 
{ 
NSString* authenticationMethod = challenge.protectionSpace.authenticationMethod; 

if (![authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) 
{ 
    completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); 
    return; 
} 

SecTrustRef trust = challenge.protectionSpace.serverTrust; 

CFIndex count = SecTrustGetCertificateCount(trust); 
CFMutableArrayRef originalCertificates = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 

for (CFIndex i = 0; i < count; i++) 
{ 
    SecCertificateRef certRef = SecTrustGetCertificateAtIndex(trust, i); 
    CFArrayAppendValue(originalCertificates, certRef); 
    CFStringRef certSummary = SecCertificateCopySubjectSummary(certRef); 
    NSLog(@"CERT %ld %@", i, certSummary); 
} 

//SecPolicyRef policyRef = SecPolicyCreateSSL(true, CFSTR("192.168.50.80")); 
SecPolicyRef policyRef = SecPolicyCreateBasicX509(); 
SecTrustRef newTrust; 

OSStatus status = SecTrustCreateWithCertificates(originalCertificates, policyRef, & newTrust); 

assert(status == noErr); 

NSString* path = [[NSBundle mainBundle] pathForResource:@"no1bcCA" ofType:@"der"]; 
NSData* data = [NSData dataWithContentsOfFile:path]; 
SecCertificateRef cert = SecCertificateCreateWithData(NULL, (CFDataRef) data); 

assert(cert); 

NSString* rootPath = [[NSBundle mainBundle] pathForResource:@"no1bcRootCA" ofType:@"der"]; 
NSData* rootData = [NSData dataWithContentsOfFile:rootPath]; 

SecCertificateRef rootCert = SecCertificateCreateWithData(NULL, (CFDataRef) rootData); 
assert(rootCert); 

SecTrustSetAnchorCertificates(newTrust, (CFArrayRef)@[(__bridge id)rootCert, (__bridge id)cert]); 
SecTrustSetAnchorCertificatesOnly(newTrust, NO); 

SecTrustResultType trustResult; 

SecTrustEvaluate(newTrust, &trustResult); 

if (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed) 
{ 
    NSURLCredential* credential = [NSURLCredential credentialForTrust:newTrust]; 
    completionHandler(NSURLSessionAuthChallengeUseCredential, credential); 

} 
else 
{ 

completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); 
} 
} 

のでtrustResultkSecTrustResultUnspecifiedですが、私のNSURLSessionDataTaskの完了ハンドラに私はまだ、次のエラーが表示さ:私は回復の提案を愛する

Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x6000003040b0>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, NSErrorPeerCertificateChainKey=(
"<cert(0x7f81ef80ca00) s: sems.no1bc.local i: no1bcCA>", 
"<cert(0x7f81ef80d400) s: no1bcCA i: no1bcRootCA>", 
"<cert(0x7f81ef82b800) s: no1bcRootCA i: no1bcRootCA>" 
), NSUnderlyingError=0x604000255030 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x6000003040b0>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=(
"<cert(0x7f81ef80ca00) s: sems.no1bc.local i: no1bcCA>", 
"<cert(0x7f81ef80d400) s: no1bcCA i: no1bcRootCA>", 
"<cert(0x7f81ef82b800) s: no1bcRootCA i: no1bcRootCA>" 
)}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://192.168.50.80/pgpuniversaldesktop, NSErrorFailingURLStringKey=https://192.168.50.80/pgpuniversaldesktop, NSErrorClientCertificateStateKey=0} 

を。それは

Would you like to connect to the server anyway?

はい、私は言うでしょうか?私は何をしますか?

<key>NSAppTransportSecurity</key> 
<dict> 
    <key>NSExceptionDomains</key> 
    <dict> 
     <key>192.168.50.80</key> 
     <dict> 
      <key>NSIncludesSubdomains</key> 
      <true/> 
      <key>NSExceptionAllowsInsecureHTTPLoads</key> 
      <true/> 
      <key>NSExceptionMinimumTLSVersion</key> 
      <string>TLSv1.2</string> 
      <key>NSExceptionRequiresForwardSecrecy</key> 
      <false/> 
      <key>NSRequiresCertificateTransparency</key> 
      <false/> 
     </dict> 
    </dict> 
</dict> 

それが助けたことがない:

別に私もATSでプレイしようとしたことすべてから、これは私がplistファイルに入れものです。だから、私は明示的にiOSに言っています:「このサーバを信頼し、信頼してください。」しかし、そうはしません。理由は何でしょうか?システムを強制的にサーバーを信頼させるにはどうすればよいですか?とにかく私はどうしたらサーバーに接続するのですか?

Macアプリケーションからこのコードを実行すると問題なく動作するのは面白いです。しかし、iOSで動作しない

答えて

0

サーバーが古いTLSを実行していたことが判明しました。 MacはiOSではなく、それに対処することができたので、何に関係なくサーバに接続することはできませんでした。ソリューションはサーバーを修正することでした

0

iOS 11では、明らかにそのドメインに対してNSExceptionRequiresForwardSecrecyfalseを設定する必要があります。それ以外の場合、App Transport Securityはカスタム証明書がカスタム認証コードに到達することさえできません。これは間違いなくバグです。

詳細については、Appleの開発者フォーラムのthis threadを参照してください。

関連する問題