14
NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)

非常に、非常にイライラします!私はこれで何時間も髪を引っ張っています。Linode サーバーで自己署名証明書を使用しています。ポートは 8000 で、443 では動作しませんでした。これが理由だとは思いませんが。これが私のコードです。99% ボイラープレートです。

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.myserver.com:8000/test.json"]];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];

下部に:

#pragma mark NSURLConnectionDelegate

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
    NSLog(@"protectionSpace: %@", [protectionSpace authenticationMethod]);

    // We only know how to handle NTLM authentication.
    if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodNTLM])
        return YES;

    // Explicitly reject ServerTrust. This is occasionally sent by IIS.
    if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust])
        return NO;

    return NO;
}

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
    [[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    NSLog(@"%@", response);
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    NSLog(@"%@", data);
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    NSLog(@"didFailWithError");
    NSLog([NSString stringWithFormat:@"Connection failed: %@", [error description]]);
}

OMGヘルプ!

アップデート

このデリゲート メソッドで動作しました。返信は来ていますが、問題があります。

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
    [[challenge sender] useCredential:[NSURLCredential
                                       credentialWithUser:@"user"
                                       password:@"password"
                                       persistence:NSURLCredentialPersistencePermanent] forAuthenticationChallenge:challenge];

}

私が提供した「ユーザー」と「パスワード」は完全にランダムであり、サーバーによってチェックされません。サーバーで接続を受け入れる前に資格情報を確認するにはどうすればよいですか?

編集: Node.js サーバーを実行しています

4

2 に答える 2

8

対応するエラーの説明を取得すると役立つ場合があります。

したがって、最初のエラー ドメインkCFStreamErrorDomainSSLは、エラー コードが Security/SecureTransport.h で定義されている SSL エラー コードであることを意味します。

kCFStreamErrorDomainSSL、-9813 の意味:

errSSLNoRootCert = -9813, /* cert chain not verified by root */

つまり、信頼できるルート証明書がなく、その認証の失敗により接続が失敗するということです。

サーバー信頼認証のためにデバイスにルート証明書を提供すれば問題ありません。

自己署名証明書を使用してサーバー信頼認証を実装するには、いくつかのアプローチがあり、一方は他方よりも安全です。

最も単純な方法は、アプリのバンドルに保存されている自己署名証明書を必要とし、取得して単純にバイト比較します。次に例を示します。

自己署名証明書によるサーバー信頼認証の実装

これらも必読です: Technical Note TN2232 HTTPS Server Trust Evaluation and Technical Q&A QA1360 Describing the kSecTrustResultUnspecified error .

より好ましいアプローチは、自分でできる CA (認証局) を使用することです。つまり、独自の CA と、この CA で署名された証明書を作成します。

手順は似ています。

  1. アプリで CA のルート証明書の DER ファイルをバンドルします。
  2. サーバー信頼認証を次のように処理します。

    1. 認証チャレンジを取得する
    2. チャレンジから信頼オブジェクトを取得する
    3. バンドル内のデータから証明書オブジェクトを作成します
    4. function を使用して、信頼オブジェクトへのアンカーとして証明書オブジェクトを設定しますSecTrustSetAnchorCertificates
    5. 信頼を評価する
于 2013-08-03T15:08:10.053 に答える
2

これで実際に問題が解決するかどうかはわかりませんが、役立つ場合があります。あなたが使用する必要があります

– connection:willSendRequestForAuthenticationChallenge:

他の方法は推奨されていないためです。NSURLConnectionDelegate プロトコルの概要を見てみましょう

于 2013-08-03T14:01:28.673 に答える