Mój serwer udostępnia kilka metod uwierzytelniania: NTLM i skrót.
Mój klient iOS nie obsługuje uwierzytelniania NTLM, więc zaimplementowałem delegata connection:willSendRequestForAuthenticationChallenge:
, aby odrzucić NTLM, a następnie użyć poprawnego poświadczenia tylko dla wyzwalacza uwierzytelniania digest.
Wszystko działa poprawnie na iOS 7 do tej pory.NSURLConnectionDelegate willSendRequestForAuthenticationChallenge nie zostanie wywołany na iOS 8
Ale na iOS 8, znalazłem dziwne zachowanie:
Delegat connection:willSendRequestForAuthenticationChallenge:
nie będzie wywoływany w większości czasu (95%) !!
mam ten błąd zamiast:
Error: Error Domain=NSPOSIXErrorDomain Code=54 "The operation couldn’t be completed. Connection reset by peer"
UserInfo=0x16520fb0 {_kCFStreamErrorCodeKey=54,
NSErrorPeerAddressKey=<CFData 0x16682e40 [0x2f752440]>{length = 16, capacity = 16, bytes = 0x10020d7eac12780b0000000000000000},
NSErrorFailingURLKey=http://SERVER_IP:SERVER_PORT/Tunnel/Message.aspx,
NSErrorFailingURLStringKey=http://SERVER_IP:SERVER_PORT/Tunnel/Message.aspx,
_kCFStreamErrorDomainKey=1}
Tylko 5% czasu delegat jest poprawnie nazwie i pracy jak zwykle.
Poniżej przedstawiono sposób wyślę moją prośbę do serwera i obsługiwać wyzwanie uwierzytelnienia: prace
- (void)postRequest
{
NSString *IP = SERVER_IP;
int port = SERVER_PORT;
NSString *url = [NSString stringWithFormat:@"http://%@:%d/Tunnel/Message.aspx", IP, port];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/xml" forHTTPHeaderField:@"Content-Type"];
NSString *xml = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?><GetServerInfo></GetServerInfo>"];
[request setHTTPBody: [xml dataUsingEncoding:NSUTF8StringEncoding]];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
NSLog(@"%@", challenge.protectionSpace);
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPDigest])
{
if ([challenge previousFailureCount] == 0)
{
[[challenge sender] useCredential:[NSURLCredential credentialWithUser:USERNAME
password:PASSWORD
persistence:NSURLCredentialPersistenceNone]
forAuthenticationChallenge:challenge];
}
else
{
[[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];
}
}
else
{
[[challenge sender] rejectProtectionSpaceAndContinueWithChallenge:challenge];
}
}
Ci kod na iOS 7 willSendRequestForAuthenticationChallenge
sprawdzony kilkakrotnie podczas wyzwaniu uwierzytelnienia, ale nawet nie nazywa się każdy raz na iOS 8!
Czy to może być błąd systemu iOS 8 lub coś się zmieniło od iOS 8?
Zaktualizowano. Dzięki za przypomnienie. – rensakura
Nawiasem mówiąc, użyłem twojego kodu na iOS 8 przeciwko mojemu podstawowemu serwerowi auth i działało dobrze (chociaż oczywiście zastąpiłem twój digest ref z podstawowym). Sugerowałbym oglądanie tego w [Charles] (http://charlesproxy.com) (lub podobnym narzędziu) i zobacz, jak reaguje twój serwer. Powtórz proces w iOS 7.1 i porównaj. Port i nazwa serwera wydają mi się podejrzane, ale mówisz, że kiedyś działały, więc domyślam się, że to nie to. – Rob
Niestety pamiętam, jak ios7 łamie NTLM w wydaniu. Porównanie wymiany ruchu, zgodnie z wcześniejszym zaleceniem, będzie przydatne w przypadku wszelkich błędów zgłaszanych przez firmę Apple. Jeśli masz konto programisty, sprawdź # 17832727, a także następujące wątki na forum: https://devforums.apple.com/message/1042503#1042503, https://devforums.apple.com/message/1042505#1042505 – garthoid