SSL 웹 페이지에 연결하는 다음과 같은 간단한 코드가 있습니다.
NSMutableURLRequest *urlRequest=[NSMutableURLRequest requestWithURL:url];
[ NSURLConnection sendSynchronousRequest: urlRequest returningResponse: nil error: &error ];
인증서가 자체 서명 된 인증서 인 경우 오류가 발생하는 것을 제외하고 Error Domain=NSURLErrorDomain Code=-1202 UserInfo=0xd29930 "untrusted server certificate".
어쨌든 (브라우저에서 수락을 누를 수있는 것처럼) 연결을 수락하도록 설정하거나 우회하는 방법이 있습니까?
답변
이를 위해 지원되는 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 (많이)에 자사의 메시지를 보낼 수 있습니다
답변
개인 API를 사용하지 않으려는 경우 (또는 사용할 수없는 경우) ASIHTTPRequest 라는 오픈 소스 (BSD 라이센스) 라이브러리가 있으며 하위 레벨을 감싸는 래퍼를 제공합니다 CFNetwork APIs
. 그들은 최근에 HTTPS connections
자체 서명 또는 신뢰할 수없는 인증서를 -setValidatesSecureCertificate:
API 와 함께 사용할 수있는 기능을 도입했습니다 . 전체 라이브러리를 가져 오지 않으려면 소스를 동일한 기능을 직접 구현하기위한 참조로 사용할 수 있습니다.
답변
이상적으로, iOS 애플리케이션이 신뢰할 수없는 인증서를 승인해야하는 경우는 두 가지 시나리오 만 있어야합니다.
시나리오 A : 자체 서명 된 인증서를 사용하는 테스트 환경에 연결되어 있습니다.
시나리오 B : 프록시를 HTTPS
사용하여 트래픽을 MITM Proxy like Burp Suite, Fiddler, OWASP ZAP, etc.
프록시하는 경우 프록시는 자체 서명 된 CA에서 서명 한 인증서를 프록시가 반환하므로 프록시가 HTTPS
트래픽 을 캡처 할 수 있습니다.
프로덕션 호스트는 확실한 이유로 신뢰할 수없는 인증서를 사용해서는 안됩니다 .
테스트를 위해 iOS 시뮬레이터가 신뢰할 수없는 인증서를 승인하도록해야하는 경우 NSURLConnection
API에서 제공하는 내장 인증서 유효성 검사를 비활성화하기 위해 응용 프로그램 논리를 변경하지 않는 것이 좋습니다 . 이 논리를 제거하지 않고 응용 프로그램을 일반에 공개하면 중간자 (man-in-the-middle) 공격에 취약 할 수 있습니다.
테스트 목적으로 신뢰할 수없는 인증서를 승인하는 권장 방법은 인증서에 서명 한 인증 기관 (CA) 인증서를 iOS 시뮬레이터 또는 iOS 장치로 가져 오는 것입니다. iOS 시뮬레이터 에서이 작업을 수행하는 방법을 보여주는 빠른 블로그 게시물을 작성했습니다.
iOS 시뮬레이터를 사용하여 신뢰할 수없는 인증서 수락
답변
NSURLRequest
라는 개인 메소드가 있으며 setAllowsAnyHTTPSCertificate:forHost:
원하는 것을 정확하게 수행합니다. 범주 allowsAnyHTTPSCertificateForHost:
를 NSURLRequest
통해 메서드를 정의하고 YES
재정의하려는 호스트에 대해 반환하도록 설정할 수 있습니다.
답변
허용 된 답변을 보완하기 위해 훨씬 나은 보안을 위해 서버 인증서 또는 자체 루트 CA 인증서를 키 체인 ( https : //.com/a/9941559/1432048 )에 추가 할 수 있지만 NSURLConnection만으로는 NSURLConnection을 만들 수 없습니다 자체 서명 된 서버를 자동으로 인증하십시오. 여전히 아래 코드를 NSURLConnection 델리게이트 에 추가해야하며, Apple 샘플 코드 AdvancedURLConnections 에서 복사되었으며, 애플 샘플 코드에서 두 개의 파일 (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];
}
답변
나는 이것에 대해 어떤 신용도 취할 수 없지만, 내가 찾은 것은 내 요구에 정말 효과적이었습니다. 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;
}
답변
iOS 9에서 모든 유효하지 않거나 자체 서명 된 인증서에 대해 SSL 연결이 실패합니다. 이는 iOS 9.0 이상 및 OS X 10.11 이상에서 새로운 App Transport Security 기능 의 기본 동작입니다 .
당신은이 동작을 무시할 수 있습니다 Info.plist
설정하여, NSAllowsArbitraryLoads
에 YES
에서 NSAppTransportSecurity
사전. 그러나 테스트 목적으로 만이 설정을 재정의하는 것이 좋습니다.