このエラーが発生します
The certificate for this server is invalid. You might be connecting to a server
that is pretending to be "server addres goes here" which could put your
confidential information at risk."
私はこの方法を使用しています:
[NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
どうすればこれを修正できますか?
私はこのコードを試しました:
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
delegate:self];
しかし、didReceiveResponseメソッドでEXC_BAD_ACCESSを取得します。
機密情報を送信していない場合は、無効な証明書を単に無視することができます。 この記事 それを行う方法を説明します。これは、その記事で説明されているメソッドの1つに対する Alexandre Colucci による実装例です。
基本的に、@implementation
のすぐ上にダミーインターフェイスを定義する必要があります。
@interface NSURLRequest (DummyInterface)
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)Host;
+ (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)Host;
@end
そして、sendSynchronousRequest
を呼び出す前に、ダミーインターフェイスで定義したプライベートメソッドを呼び出します。
[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[URL Host]];
新しいものを使用した正しい(非推奨ではない、プライベートではない)方法:
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
Appleが指定したメソッドはNSURLConnectionDelegatesに使用する必要があります)は、保護スペースに提供された資格情報を使用してServerTrustメソッドに応答します(これにより、次の接続が可能になります。
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
NSLog(@"Ignoring SSL");
SecTrustRef trust = challenge.protectionSpace.serverTrust;
NSURLCredential *cred;
cred = [NSURLCredential credentialForTrust:trust];
[challenge.sender useCredential:cred forAuthenticationChallenge:challenge];
return;
}
// Provide your regular login credential if needed...
}
このメソッドを使用してログインしたくない場合は、使用可能な認証メソッドごとに1回、このメソッドが複数回呼び出されます。
[challenge.sender rejectProtectionSpaceAndContinueWithChallenge:challenge];
私も同様の問題を抱えていました。以下のコードスニペットを使用して解決しました:
-(void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
NSLog(@"This will execute successfully!");
if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodServerTrust) {
[[challenge sender] useCredential:[NSURLCredential credentialForTrust:[[challenge protectionSpace] serverTrust]] forAuthenticationChallenge:challenge];
}
}
以下のメソッドは非推奨であるため:
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)space { ... }
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { ... }
デリゲートをselfとして設定したので、そのリクエストを送信するクラスにNSURLConnectionDelegateの一部を実装することで、これを修正できます。
これを実装します:
-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
これを行うことによって:
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
注:これは、本番環境で使用するソリューションではありません。証明書が存在するのには理由があります! :)
これは、「エラーを無視する方法」という質問には答えません。それは無責任です。
むしろ、サーバーを認証するCAをロードして、接続を期待どおりに続行できるようにする方法を示しています。以下では、CAはアプリにバンドルされており、ca-cert.der
と呼ばれます。そのDER(PEMではなく)でエンコードされた証明書。
また、Appleの テクニカルノートTN2232 HTTPSサーバーの信頼性評価 もご覧ください。 kSecTrustResultUnspecified
は成功です。 テクニカルQ&A QA1360 kSecTrustResultUnspecifiedエラーの説明 を参照してください。
-(BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:
(NSURLProtectionSpace*)space
{
return [[space authenticationMethod] isEqualToString: NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:
(NSURLAuthenticationChallenge *)challenge
{
if ([[[challenge protectionSpace] authenticationMethod] isEqualToString: NSURLAuthenticationMethodServerTrust])
{
do
{
SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
NSCAssert(serverTrust != nil, @"serverTrust is nil");
if(nil == serverTrust)
break; /* failed */
NSData* caCert = [NSData dataWithContentsOfFile:@"ca-cert.der"];
NSCAssert(caCert != nil, @"caCert is nil");
if(nil == caCert)
break; /* failed */
SecCertificateRef caRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)caCert);
NSCAssert(caRef != nil, @"caRef is nil");
if(nil == caRef)
break; /* failed */
NSArray* caArray = [NSArray arrayWithObject:(__bridge id)(caRef)];
NSCAssert(caArray != nil, @"caArray is nil");
if(nil == caArray)
break; /* failed */
OSStatus status = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)caArray);
NSCAssert(errSecSuccess == status, @"SecTrustSetAnchorCertificates failed");
if(!(errSecSuccess == status))
break; /* failed */
SecTrustResultType result = -1;
status = SecTrustEvaluate(serverTrust, &result);
if(!(errSecSuccess == status))
break; /* failed */
NSLog(@"Result: %d", result);
/* This test looks for a "SUCCESS" */
/* kSecTrustResultUnspecified and kSecTrustResultProceed are success */
if(result != kSecTrustResultUnspecified && result != kSecTrustResultProceed)
break; /* failed */
#if 0
/* Alternate test looks for a "NOT FAILURE" */
/* Treat kSecTrustResultConfirm and kSecTrustResultRecoverableTrustFailure as success */
/* since the user will likely tap-through to see the dancing bunnies */
if(result == kSecTrustResultDeny || result == kSecTrustResultFatalTrustFailure || result == kSecTrustResultOtherError)
break; /* failed to trust cert (good in this case) */
#endif
// The only good exit point
return [[challenge sender] useCredential: [NSURLCredential credentialForTrust: serverTrust]
forAuthenticationChallenge: challenge];
} while(0);
}
// Bad dog
return [[challenge sender] cancelAuthenticationChallenge: challenge];
}
HTTPSURLを使用していますか。その場合は、ブラウザのURLに移動して、証明書を確認してください。証明書が使用しようとしているドメインまたはサブドメインに対して有効であること、およびすべての中間証明書がサーバーにインストールされていることを確認してください。これと同様の問題が発生しました。解決策は、中間証明書をインストールすることでした。