Нужно просматривать сайт с самозаверяющим сертификатом и http аутентификацией
У меня возникают проблемы при просмотре веб-сайта, который имеет самозаверяющий сертификат, а также требует HTTP-аутентификации. В настоящее время я пытаюсь реализовать это с помощью Как отобразить вызов аутентификации в UIWebView? и UIWebView для просмотра самоподписанных веб-сайтов (нет частного API, не NSURLConnection) - возможно ли это? в качестве руководства о том, как этого добиться. Я также пытаюсь использовать закрытый метод API для обхода самозаверяющих сертификатов, но мне трудно найти ссылку на него. Но частный заголовок API:
@interface NSURLRequest (DummyInterface)
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host;
+ (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host;
@end
Тогда у меня есть эти важные функции:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
{
NSLog(@"Did start loading: %@ auth:%d", [[request URL] absoluteString], _authenticated);
[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[URL host]];
_request=[NSURLRequest requestWithURL:URL];
if (!_authenticated) {
_authenticated = NO;
[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[URL host]];
_urlConnection = [[NSURLConnection alloc] initWithRequest:_request delegate:self];
[_urlConnection start];
[mainWebView loadRequest:_request];
return NO;
}
return YES;
}
В основном вызывает соединение nsurl для передачи учетных данных входа в систему.
#pragma mark - NURLConnection delegate
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
{
NSLog(@"WebController Got auth challange via NSURLConnection");
[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[URL host]];
if ([challenge previousFailureCount] == 0)
{
_authenticated = YES;
NSURLCredential *credential = [NSURLCredential credentialWithUser:@"username"
password:@"password"
persistence:NSURLCredentialPersistenceForSession];
[challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
NSLog(@"credential created");
} else
{
NSLog(@"previous authentication failure");
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}
а также
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
{
NSLog(@"WebController received response via NSURLConnection");
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"remote url returned error %d %@",[httpResponse statusCode],[NSHTTPURLResponse localizedStringForStatusCode:[httpResponse statusCode]]);
NSLog(@"The response is =%@",response);
_authenticated = YES;
[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[URL host]];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:URL];
[mainWebView loadRequest:urlRequest];
[_urlConnection cancel];
}
3 ответа
Это легко реализовать с помощью AFNetworking
Я сделал это путем подклассов AFHTTPRequestOperation
и добавив этот код в init
// SSL Support
[self setAuthenticationChallengeBlock:^(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge) {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
}];
[self setAuthenticationAgainstProtectionSpaceBlock:^BOOL(NSURLConnection *connection, NSURLProtectionSpace *protectionSpace) {
if([[protectionSpace 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;
}];
Вы также можете добавить свои заголовки авторизации в подкласс, что делает использование соединения в различных частях вашего приложения очень простым.
Используя приведенные ниже два метода, мы можем разрешить самозаверяющие сертификаты
-(BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace;
-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
Я ответил подробно, используя эти методы здесь
Переопределить NSURLConnectionDelegate's
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
Следующее примет любой сертификат SSL без проверки хоста и поэтому небезопасно. У вас должен быть файл ресурсов, содержащий все действительные хосты, и сравните сертификаты, используя платформу безопасности.
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
} else {
[challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];
}
}
Вы изучали использование ASIHTTPRequest? Я считаю, что у него есть методы, которые упрощают это.