AFNetworking 2.5.0を使用してSSLでアプリのネットワーク接続を保護するのに苦労しています。
自己署名の認証局を使用し、固定証明書を使用してカスタムセキュリティポリシーを実装しました。
AFNetworkingが提供する多くの構成をテストしましたが、これまでのところ運が良くありません。表示されるエラーメッセージは次のとおりです。
2015-01-05 19:03:07.191 AppName [9301:319051]ユーザージャーニーの更新エラー。エラー:Error Domain = NSURLErrorDomain Code = -1012 "操作を完了できませんでした。(NSURLErrorDomainエラー-1012。)" UserInfo = 0x7ae056b0 {NSErrorFailingURLKey = https://api.XXX.com/XXX/XXX / 、NSErrorFailingURLStringKey= https://api.XXX.com/XXX/XXX/ }
証明書は、cURLやAndroidなどの他のクライアントで正常に機能します。 HTTPを使用する場合、実装も完全に機能します。
固定された証明書とAFNetworkingに関連する問題を知っている人はいますか?はいの場合は、ご意見をお寄せください。
実装の一部を次に示します。
+ (AFSecurityPolicy*)customSecurityPolicy {
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"filename" ofType:@"der"];
NSData *certData = [NSData dataWithContentsOfFile:cerPath];
[securityPolicy setAllowInvalidCertificates:NO];
[securityPolicy setValidatesCertificateChain:NO];
[securityPolicy setPinnedCertificates:@[certData]];
return securityPolicy;
}
+ (AFHTTPRequestOperationManager*)customHttpRequestOperationManager {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.securityPolicy = [self customSecurityPolicy]; // SSL
return manager;
}
+(void)getRequestWithUrl:(NSString*)url success:(void(^)(AFHTTPRequestOperation *operation, id responseObject))success failure:(void(^) (AFHTTPRequestOperation *operation, NSError *error))failure {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
AFHTTPRequestOperationManager *manager = [HttpClient customHttpRequestOperationManager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
success(operation, responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
failure(operation, error);
}];
}
ありがとうございました!
AFNetworkingのコードを読み、変更ログを確認した後、これを機能させるために必要なことを以下に示します。
AFSSLPinningModeCertificateを使用してAFSecurityPolicyオブジェクトを作成します。
AFSecurityPolicy* policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
デフォルトでは、AFNetworkingは証明書のドメイン名を検証します。私たちの証明書はサーバーごとに生成され、それらのすべてがドメイン名を持つわけではないので、それを無効にする必要があります:
[policy setValidatesDomainName:NO];
証明書は自己署名されているため、技術的には「無効」であるため、同様に許可する必要があります。
[policy setAllowInvalidCertificates:YES];
最後に、AFNetworkingは証明書チェーンの最上部まで証明書を検証しようとします。これは、私たちにとってはCAにチェーンを移動するだけのように思えますが、何らかの理由でそれを無効にする必要があります。
[policy setValidatesCertificateChain:NO];
以上です!既に実行しているように、リクエストマネージャーでセキュリティポリシーを設定します。
要約すると、投稿したコードで本当に変更する必要があるのは次のとおりです。
A) David Caunt 前述のように、ピン留めモードをAFSSLPinningModeNone
からAFSSLPinningModeCertificate
に変更します
そして
B)次の行を追加して、ドメイン名の検証を無効にします:[policy setValidatesDomainName:NO]
もう1つの注意点として、AFNetworkingは自動的にバンドルの.cerファイルを確認するため、証明書の名前を.cer拡張子に変更する場合、コードを削除してバンドルから証明書データを取得し、固定された証明書を設定できます。
マネージャーが初期化されているため、次のことができます。
manager.securityPolicy.allowInvalidCertificates = YES;
manager.securityPolicy.validatesDomainName = NO;
自己署名証明書で機能します
このエラーが発生しました、Error Domain=NSURLErrorDomain Code=-1012 NSErrorFailingURLStringKey
以下の変更だけでうまくいきました。
self.validatesDomainName = NO;
AFSecurityPolicy
モードSSLPinningMode
でAFSSLPinningModeNone
を作成しています。
AFNetworkingがAFSSLPinningModeNone
に設定された固定モードでサーバーを信頼するには、allowInvalidCertificates
をYES
に設定する必要がありますが、これはoppositeあなたは達成しようとしています。
代わりに、ピン留めモードAFSSLPinningModeCertificate
またはAFSSLPinningModePublicKey
を使用してセキュリティポリシーを作成する必要があります。
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
- (AFSecurityPolicy *)securityPolicy {
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"*.something.co.in" ofType:@"cer"];
NSData *certData = [NSData dataWithContentsOfFile:cerPath];
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
[securityPolicy setAllowInvalidCertificates:YES];
[securityPolicy setPinnedCertificates:@[certData]];
[securityPolicy setValidatesDomainName:NO];
[securityPolicy setValidatesCertificateChain:NO];
return securityPolicy;
}
これは何らかの理由でうまくいきました。私のアプリの他の接続はこれらすべてのステップを踏まずに機能するため、これがどのように変化するかはまだわかりません。
これは、セキュリティポリシーを生成するエラーのようです-
- (AFSecurityPolicy *)securityPolicy {
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"*.something.co.in" ofType:@"cer"];
NSData *certData = [NSData dataWithContentsOfFile:cerPath];
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
[securityPolicy setAllowInvalidCertificates:NO];
[securityPolicy setPinnedCertificates:@[certData]];
[securityPolicy setValidatesDomainName:YES];
return securityPolicy;
}
「壊れていない場合は修正しない」ルールにこだわる
クライアント証明書がなくても警告を消すだけの場合、ポリシーは次のようになります。
AFSecurityPolicy* policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
[policy setValidatesDomainName:YES];
[policy setAllowInvalidCertificates:NO];
私にとっては、use_frameworks!
はPodfile
に設定します-プロジェクトはSwiftを使用せず、Pods
にAFNetworking
を使用していました。アウト、私のために問題を修正しました。
多くのブラウザはサードパーティからの証明書ファイルをキャッシュするため、常にロードする必要がないため、同様の問題に対処した場合、ブラウザのHTTPS接続を介して正常に見えることが一般的です。したがって、信じられるように導かれた可能性があるため、証明書チェーンが完全に信頼されていない可能性があります。
言い換えれば、ブラウザに安全に接続することは問題ないと思われるかもしれませんが、AFNetworkingの設定によっては、アプリは実際に証明書チェーンを受け入れません。設定が適切であることを確認したら、次のステップは、証明書チェーンが実際にあなたが思っているほど良いことを確認することです。 SSL Detectiveというアプリをダウンロードして、サーバーに照会します。 www.ssldecoder.org を使用することもできます。チェーンに赤い(信頼できない)アイテムがないことを確認してください。ある場合は、サーバー上の証明書のセットアップを変更します。
AFNetworkingの設定は次のとおりです。
[securityPolicy setAllowInvalidCertificates:NO];
[securityPolicy setValidatesCertificateChain:NO];
自己署名されているため、証明書チェーンが気に入らない可能性があります。また、それらをYESに切り替える必要があります。