AFNetworkingの原作者が解決できない問題:ipを使用してhttpsサイトに直接アクセスする方法
4566 ワード
背景
最近AppはDNSが解析できないという異常を報告しているようで、この問題を解決しようとしている.収集された資料は少なく、AFNの原作者さえこれが無解な問題である可能性があると判断している.https://github.com/AFNetworking/AFNetworking/issues/2954しかし、最終的にはstackoverflowのヒントに頼って、利用可能なソリューションを順調に見つけて統合しました.大喜び、君とシェア!
問題の説明
IPを介して直接ウェブサイトにアクセスすることで、DNSハイジャック問題を解決することができる.DNSハイジャックは、コンピュータのhostファイルシミュレーションを修正することができます.HTTPリクエストの場合、ipアドレスを使用してインタフェースに直接アクセスし、headerのHostフィールドに合わせて元のドメイン名情報を持ち込めばよい.httpリクエストであれば面倒ですが、
Overriding TLS Chain Validation Correctly
が必要です.curlには-resolve
の方法があり、指定されたipを使用してhttpサイトにアクセスすることができます.iOSにcurlライブラリを統合してもいいはずですが、変更が大きすぎて検証されていません.サーバIPが頻繁に変化する場合、httpDNSサービスを使用する必要がある場合があります.https://www.dnspod.cn/httpdns. ソリューションの検討
1.最も直接的な方法は無効なSSL証明書を許可することであり、生産環境は使用を推奨しない。
2.AFNのソースコードを部分的に書き換える必要がある方法.
/** , ip https .
Trusted domain, this domain for support via IP access HTTPS links.
*/
@property(nonatomic, strong) NSMutableArray * trustHostnames;
- (void)connection:(NSURLConnection *)connection
willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if (self.authenticationChallenge) {
self.authenticationChallenge(connection, challenge);
return;
}
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
/* , : ip https .
Add trusted domain name to support: direct use of IP access specific HTTPS server.*/
for (NSString * trustHostname in [self trustHostnames]) {
serverTrust = AFChangeHostForTrust(serverTrust, trustHostname);
}
....
static inline SecTrustRef AFChangeHostForTrust(SecTrustRef trust, NSString * trustHostname)
{
if ( ! trustHostname || [trustHostname isEqualToString:@""]) {
return trust;
}
CFMutableArrayRef newTrustPolicies = CFArrayCreateMutable(
kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
SecPolicyRef sslPolicy = SecPolicyCreateSSL(true, (CFStringRef)trustHostname);
CFArrayAppendValue(newTrustPolicies, sslPolicy);
#ifdef MAC_BACKWARDS_COMPATIBILITY
/* This technique works in OS X (v10.5 and later) */
SecTrustSetPolicies(trust, newTrustPolicies);
CFRelease(oldTrustPolicies);
return trust;
#else
/* This technique works in iOS 2 and later, or
OS X v10.7 and later */
CFMutableArrayRef certificates = CFArrayCreateMutable(
kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
/* Copy the certificates from the original trust object */
CFIndex count = SecTrustGetCertificateCount(trust);
CFIndex i=0;
for (i = 0; i < count; i++) {
SecCertificateRef item = SecTrustGetCertificateAtIndex(trust, i);
CFArrayAppendValue(certificates, item);
}
/* Create a new trust object */
SecTrustRef newtrust = NULL;
if (SecTrustCreateWithCertificates(certificates, newTrustPolicies, &newtrust) != errSecSuccess) {
/* Probably a good spot to log something. */
return NULL;
}
return newtrust;
#endif
}
/* AOP , , : ip https .*/
[AFURLConnectionOperation aspect_hookSelector:@selector(trustHostnames) withOptions:AspectPositionInstead usingBlock: ^(id<AspectInfo> info){
__autoreleasing NSArray * trustHostnames = @[@"www.example.com"];
NSInvocation *invocation = info.originalInvocation;
[invocation setReturnValue:&trustHostnames];
}error:NULL];
ここではiOS AOPライブラリを使用しています.よく知らない点はここです.http://www.ios122.com/2015/08/aspects/.