305

SSL Webページに接続するための次の簡単なコードがあります

NSMutableURLRequest *urlRequest=[NSMutableURLRequest requestWithURL:url];
[ NSURLConnection sendSynchronousRequest: urlRequest returningResponse: nil error: &error ];

証明書が自己署名されたものである場合にエラーが発生することを除いて、Error Domain=NSURLErrorDomain Code=-1202 UserInfo=0xd29930 "untrusted server certificate".とにかく接続を受け入れるように設定する方法はありますか (ブラウザーで [受け入れ] を押すことができるのと同じように)、またはそれをバイパスする方法はありますか?

4

13 に答える 13

418

これを実現するためのサポートされている API があります。次のようなものをNSURLConnectionデリゲートに追加します。

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

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
  if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
    if ([trustedHosts containsObject:challenge.protectionSpace.host])
      [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];

  [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}

connection:didReceiveAuthenticationChallenge:必要に応じてユーザーにダイアログ ボックスを表示した後など、(かなり) 後でそのメッセージを challenge.sender に送信できることに注意してください。

于 2010-01-09T15:21:35.553 に答える
36

プライベート API を使用したくない (または使用できない) 場合は、 ASIHTTPRequestというオープン ソース (BSD ライセンス) ライブラリがあり、下位レベルの .xml のラッパーを提供しますCFNetwork APIs。彼らは最近、HTTPS connections自己署名証明書または信頼されていない証明書を-setValidatesSecureCertificate:API で使用できるようにする機能を導入しました。ライブラリ全体を取り込みたくない場合は、同じ機能を自分で実装するためのリファレンスとしてソースを使用できます。

于 2009-06-10T01:19:25.187 に答える
33

理想的には、iOSアプリケーションが信頼できない証明書を受け入れる必要がある場合のシナリオは2つだけである必要があります。

シナリオA:自己署名証明書を使用しているテスト環境に接続しています。

シナリオB:プロキシHTTPSを使用してトラフィックをMITM Proxy like Burp Suite, Fiddler, OWASP ZAP, etc.プロキシしている場合プロキシは、プロキシがトラフィックをキャプチャできるように、自己署名CAによって署名された証明書を返しHTTPSます。

明らかな理由で、本番ホストは信頼できない証明書を使用しないでください。

NSURLConnectionテスト目的でiOSシミュレーターに信頼できない証明書を受け入れさせる必要がある場合は、 APIによって提供される組み込みの証明書検証を無効にするために、アプリケーションロジックを変更しないことを強くお勧めします。このロジックを削除せずにアプリケーションを公開すると、man-in-the-middle攻撃の影響を受けやすくなります。

テスト目的で信頼できない証明書を受け入れるための推奨される方法は、証明書に署名した認証局(CA)証明書をiOSシミュレーターまたはiOSデバイスにインポートすることです。iOSシミュレーターでこれを行う方法を示す簡単なブログ投稿を書きました:

iOSシミュレーターを使用して信頼できない証明書を受け入れる

于 2011-08-11T14:36:56.883 に答える
12

NSURLRequestと呼ばれるプライベートメソッドがsetAllowsAnyHTTPSCertificate:forHost:あり、これはまさにあなたが望むことを行います。allowsAnyHTTPSCertificateForHost:カテゴリを介してメソッドを定義し、オーバーライドしたいホストNSURLRequestを返すように設定できます。YES

于 2009-06-01T10:53:41.077 に答える
11

私はこれを信用することはできませんが、私が見つけたこれは私のニーズに非常にうまく機能しました. shouldAllowSelfSignedCertは私のBOOL変数です。デリゲートに追加するだけNSURLConnectionで、接続ごとにすばやくバイパスできるようになります。

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)space {
     if([[space authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust]) {
          if(shouldAllowSelfSignedCert) {
               return YES; // Self-signed cert will be accepted
          } else {
               return NO;  // Self-signed cert will be rejected
          }
          // Note: it doesn't seem to matter what you return for a proper SSL cert
          //       only self-signed certs
     }
     // If no other authentication is required, return NO for everything else
     // Otherwise maybe YES for NSURLAuthenticationMethodDefault and etc.
     return NO;
}
于 2010-02-02T19:50:59.320 に答える
11

受け入れられた回答を補完するために、セキュリティを大幅に向上させるために、サーバー証明書または独自のルート CA 証明書をキーチェーンに追加できます ( https://stackoverflow.com/a/9941559/1432048 )。ただし、これだけでは NSURLConnection は作成されません。自己署名サーバーを自動的に認証します。以下のコードを NSURLConnection デリゲートに追加する必要があります。これは Apple サンプル コードAdvancedURLConnectionsからコピーしたものであり、Apple サンプル コードからプロジェクトに 2 つのファイル (Credentials.h、Credentials.m) を追加する必要があります。

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

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
//        if ([trustedHosts containsObject:challenge.protectionSpace.host])

    OSStatus                err;
    NSURLProtectionSpace *  protectionSpace;
    SecTrustRef             trust;
    SecTrustResultType      trustResult;
    BOOL                    trusted;

    protectionSpace = [challenge protectionSpace];
    assert(protectionSpace != nil);

    trust = [protectionSpace serverTrust];
    assert(trust != NULL);
    err = SecTrustEvaluate(trust, &trustResult);
    trusted = (err == noErr) && ((trustResult == kSecTrustResultProceed) || (trustResult == kSecTrustResultUnspecified));

    // If that fails, apply our certificates as anchors and see if that helps.
    //
    // It's perfectly acceptable to apply all of our certificates to the SecTrust
    // object, and let the SecTrust object sort out the mess.  Of course, this assumes
    // that the user trusts all certificates equally in all situations, which is implicit
    // in our user interface; you could provide a more sophisticated user interface
    // to allow the user to trust certain certificates for certain sites and so on).

    if ( ! trusted ) {
        err = SecTrustSetAnchorCertificates(trust, (CFArrayRef) [Credentials sharedCredentials].certificates);
        if (err == noErr) {
            err = SecTrustEvaluate(trust, &trustResult);
        }
        trusted = (err == noErr) && ((trustResult == kSecTrustResultProceed) || (trustResult == kSecTrustResultUnspecified));
    }
    if(trusted)
        [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}

[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
于 2014-02-07T07:15:14.080 に答える
7

NSUrlConnectionNathan de Vriesによって投稿されたカテゴリの回避策は、AppStoreのプライベートAPIチェックに合格し、オブジェクトを制御できない場合に役立ちます。1つの例はNSXMLParser、指定したURLを開きますが、NSURLRequestまたはを公開しない場合NSURLConnectionです。

iOS 4でも回避策は機能しているようですが、デバイス上でのみ、シミュレーターはallowsAnyHTTPSCertificateForHost:メソッドを呼び出さなくなります。

于 2010-07-21T12:58:10.427 に答える
6

HTTPS 接続を許可するには使用する必要がNSURLConnectionDelegateあり、iOS8 には新しいコールバックがあります。

非推奨:

connection:canAuthenticateAgainstProtectionSpace:
connection:didCancelAuthenticationChallenge:
connection:didReceiveAuthenticationChallenge:

それらの代わりに、次のように宣言する必要があります。

connectionShouldUseCredentialStorage:- URL ローダーが接続の認証に資格情報ストレージを使用する必要があるかどうかを判断するために送信されます。

connection:willSendRequestForAuthenticationChallenge:- 接続が認証チャレンジのリクエストを送信することをデリゲートに伝えます。

非推奨のメソッドと同じようにwillSendRequestForAuthenticationChallenge使用できますchallenge。たとえば、次のようになります。

// Trusting and not trusting connection to host: Self-signed certificate
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
于 2015-02-13T00:46:34.363 に答える
3

自己生成された証明書に対して適切に認証できるようにするいくつかの要点コードを投稿しました(私がメモした他の誰かの作品に基づいています)(および無料の証明書を取得する方法 - Cocoaneticsのコメントの下部を参照してください)

私のコードはこちらgithub

于 2012-03-16T23:25:34.003 に答える
2

このコードを使用できます

-(void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
     if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodServerTrust)
     {
         [[challenge sender] useCredential:[NSURLCredential credentialForTrust:[[challenge protectionSpace] serverTrust]] forAuthenticationChallenge:challenge];
     }
}

-connection:willSendRequestForAuthenticationChallenge:これらの非推奨メソッドの代わりに使用

非推奨:

-(BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace  
-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 
-(void)connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
于 2017-01-07T12:31:23.627 に答える
1

AFNetworkingを使用すると、以下のコードで https Web サービスを正常に使用できました。

NSString *aStrServerUrl = WS_URL;

// Initialize AFHTTPRequestOperationManager...
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];

[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
manager.securityPolicy.allowInvalidCertificates = YES; 
[manager POST:aStrServerUrl parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject)
{
    successBlock(operation, responseObject);

} failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
    errorBlock(operation, error);
}];
于 2015-09-07T09:37:55.773 に答える