Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

iOS.Dev.Urawa#4-NSURLConnectionデリゲートメソッドと認証

4,173 views

Published on

iOS.Dev.Urawa#4
2011/6/22
NSURLConnectionデリゲートメソッドと認証
新居雅行

Published in: Technology
  • Was a little hesitant about using ⇒⇒⇒WRITE-MY-PAPER.net ⇐⇐⇐ at first, but am very happy that I did. The writer was able to write my paper by the deadline and it was very well written. So guys don’t hesitate to use it.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Dating for everyone is here: ❤❤❤ http://bit.ly/36cXjBY ❤❤❤
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Dating direct: ❤❤❤ http://bit.ly/36cXjBY ❤❤❤
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

iOS.Dev.Urawa#4-NSURLConnectionデリゲートメソッドと認証

  1. 1. NSURLConnectionのデ リゲートメソッドと認証 iOS.Developer勉強会.Urawa #4 2011/6/22 Masayuki Nii 1
  2. 2. Agenda NSURLConnectionを利用した通信処理 状況別のメソッド呼び出し順序 2
  3. 3. NSURLConnectionの最低限の使用法 NSURLRequest等からインスタンス化 受信を始めると、以下のメドッドが呼び出される • - (void)connection:(NSURLConnection *)connection  didReceiveData:(NSData *)data 受信が完了すると、以下のメソッドが呼び出される • - (void)connectionDidFinishLoading:(NSURLConnection *)connection いちおうエラー処理くらいしよう • - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 3
  4. 4. しかしながら… これであらゆる場合に対処できるのか? あらゆるエラーを取得できるのか? SSLや認証はこれでいいのか? 全メソッドをインプリメントしていろいろな状況で動か してみる • • プロジェクト:ConnectionTest テスト:iOS 4.3 (シミュレータ)、Mac OS X Server 10.6.x 4
  5. 5. すべてのデリゲートメソッド(1) 通信前 • - (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse 通信中 • • - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 5
  6. 6. すべてのデリゲートメソッド(2) 通信後 • • • - (void)connectionDidFinishLoading:(NSURLConnection *)connection - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error - (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite: (NSInteger)totalBytesExpectedToWrite 6
  7. 7. すべてのデリゲートメソッド(3) 認証 • • • • - (BOOL)connectionShouldUseCredentialStorage: (NSURLConnection *)connection - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace: (NSURLProtectionSpace *)protectionSpace - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge - (void)connection:(NSURLConnection *)connection didCancelAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge 7
  8. 8. - (void)downloadData: (NSString *)urlString { NSURL *url = [NSURL URLWithString: urlString]; NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL: url]; NSLog( @"urlString = %@", urlString ); self.receivedData = [NSMutableData data]; NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest: urlRequest delegate: self]; if ( connection == nil ) { NSLog( @"ERROR: NSURLConnection is nil" ); } } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { NSLog( @"Calling: connection:didReceiveData:" ); [self.receivedData appendData: data]; } 基本3メソッド - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { NSLog( @"Calling: connection:didFailWithError: %@", error ); self.receivedData = nil; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { NSLog( @"Calling: connectionDidFinishLoading:" ); [connection release]; NSLog( @"receivedData = %@", [[[NSString alloc] initWithData: self.receivedData encoding: NSUTF8StringEncoding] autorelease] ); self.receivedData = nil; } 8
  9. 9. - (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { NSHTTPURLResponse *httpRes = (NSHTTPURLResponse *)response; NSLog( @"Calling: connection:didReceiveResponse: status code=%d", [httpRes statusCode] ); } - (void) connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { NSLog( @"Calling: connection:didCancelAuthenticationChallenge: %@", challenge ); } - (void) connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite { NSLog( @"Calling: connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:" ); } - (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse { NSLog( @"Calling: connection:willSendRequest:redirectResponse: %@", redirectResponse ); return request; } - (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection { NSLog( @"Calling: connectionShouldUseCredentialStorage:" ); return NO; } 9
  10. 10. ネットワーク関連エラー 10
  11. 11. 普通にうまくいった場合 didReceiveResponseが先に呼ばれる urlString = http://msyk.dyndns.org/test.php Calling: connection:willSendRequest:redirectResponse: (null) Calling: connectionShouldUseCredentialStorage: Calling: connection:didReceiveResponse: status code=200 Calling: connection:didReceiveData: : Calling: connection:didReceiveData: Calling: connectionDidFinishLoading: receivedData = 012345678901234567890… 11
  12. 12. 存在しないファイルにアクセスした場合 didFailWithError:は呼ばれない didReceiveResponse:でのステータスコードのチェッ クが必要 urlString = http://msyk.dyndns.org/test1.php Calling: connection:willSendRequest:redirectResponse: (null) Calling: connectionShouldUseCredentialStorage: Calling: connection:didReceiveResponse: status code=404 Calling: connection:didReceiveData: Calling: connectionDidFinishLoading: receivedData = <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>404 Not Found</title> 12
  13. 13. 存在しないURLに接続しようとした didFailWithError:が呼び出される エラーは「サーバが見つからない」 urlString = http://msyk1234.dyndns.org/ Calling: connection:willSendRequest:redirectResponse: (null) Calling: connectionShouldUseCredentialStorage: Calling: connection:didFailWithError: Error Domain=NSURLErrorDomain Code=-1003 "A server with the specified hostname could not be found." UserInfo=0x7013250 {NSErrorFailingURLStringKey=http:// msyk1234.dyndns.org/, NSErrorFailingURLKey=http:// msyk1234.dyndns.org/, NSLocalizedDescription=A server with the specified hostname could not be found., NSUnderlyingError=0x7013190 "A server with the specified hostname could not be found."} 13
  14. 14. DNSの応答がない場合 didFailWithError:が呼び出される エラーは「タイムアウト」 urlString = http://msyk.dyndns.org/ Calling: connection:willSendRequest:redirectResponse: (null) Calling: connectionShouldUseCredentialStorage: Calling: connection:didFailWithError: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo=0x8b14b50 {NSErrorFailingURLStringKey=http://msyk.dyndns.org/, NSErrorFailingURLKey=http://msyk.dyndns.org/, NSLocalizedDescription=The request timed out., NSUnderlyingError=0x8b132d0 "The request timed out."} 14
  15. 15. 到達しないIPアドレスを指定した場合 didFailWithError:が呼び出される エラーは「タイムアウト」 urlString = http://192.168.1.98/ Calling: connection:willSendRequest:redirectResponse: (null) Calling: connectionShouldUseCredentialStorage: Calling: connection:didFailWithError: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo=0x4b25350 {NSErrorFailingURLStringKey=http:// 192.168.1.98/, NSErrorFailingURLKey=http://192.168.1.98/, NSLocalizedDescription=The request timed out., NSUnderlyingError=0x4b22330 "The request timed out."} 15
  16. 16. すべてのネットワーク接続がオフ(1) didFailWithError:が呼び出される エラーは「インターネットがオフライン」 urlString = http://msyk.dyndns.org/ Calling: connection:willSendRequest:redirectResponse: (null) Calling: connectionShouldUseCredentialStorage: Calling: connection:didFailWithError: Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo=0x4b34070 {NSErrorFailingURLStringKey=http://msyk.dyndns.org/, NSErrorFailingURLKey=http://msyk.dyndns.org/, NSLocalizedDescription=The Internet connection appears to be offline., NSUnderlyingError=0x4b0dbe0 "The Internet connection appears to be offline."} 16
  17. 17. すべてのネットワーク接続がオフ(2) URLにIPアドレスを指定した場合 didFailWithError:が呼び出される エラーは「サーバに接続できない」 urlString = http://10.0.1.1/ Calling: connection:willSendRequest:redirectResponse: (null) Calling: connectionShouldUseCredentialStorage: Calling: connection:didFailWithError: Error Domain=NSURLErrorDomain Code=-1004 "Could not connect to the server." UserInfo=0x4e2fa70 {NSErrorFailingURLStringKey=http://10.0.1.1/, NSErrorFailingURLKey=http:// 10.0.1.1/, NSLocalizedDescription=Could not connect to the server., NSUnderlyingError=0x4e0c4c0 "Could not connect to the server."} 17
  18. 18. リダイレクト 基本3メソッドだけの場合、何もしなくてもOK willSendRequest:redirectResponse:の呼び出し2回 urlString = http://msyk.dyndns.org/test.php Calling: connection:willSendRequest:redirectResponse: (null) Calling: connectionShouldUseCredentialStorage: Calling: connection:willSendRequest:redirectResponse: <NSHTTPURLResponse: 0x6834f60> Calling: connection:didReceiveResponse: status code=200 Calling: connection:didReceiveData: : Calling: connection:didReceiveData: Calling: connectionDidFinishLoading: receivedData = <html lang="ja"> <head> 18
  19. 19. SSL 19
  20. 20. 正しい証明書のサイト(1) 基本3メソッドだけの場合、何もしなくても接続可能 認証関連のメソッドを単に組み込んだだけの場合だと、 以下のように通信は正しくできない urlString = https://msyk.net/ Calling: connection:willSendRequest:redirectResponse: (null) Calling: connectionShouldUseCredentialStorage: Calling: connection:canAuthenticateAgainstProtectionSpace: <NSURLProtectionSpace: 0x6502 Calling: connection:didReceiveAuthenticationChallenge: <NSURLAuthenticationChallenge: 0x ****何も受信できていない 20
  21. 21. - (BOOL) connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace { NSString *authMethod = [protectionSpace authenticationMethod]; NSLog( @"Calling: connection:canAuthenticateAgainstProtectionSpace: " " auth method=%@/host=%@", authMethod, [protectionSpace host] ); if ( [authMethod isEqualToString: NSURLAuthenticationMethodServerTrust] ) secTrustRef = [protectionSpace serverTrust]; if (secTrustRef != NULL) { SecTrustResultType result; OSErr er = SecTrustEvaluate( secTrustRef, &result ); if ( er != noErr) { return NO; } if ( result == kSecTrustResultRecoverableTrustFailure ) { NSLog( @"---SecTrustResultRecoverableTrustFailure" ); } NSLog( @"---Return YES" ); return YES; } } if ( [authMethod isEqualToString: NSURLAuthenticationMethodDefault] ) { NSLog( @"---Return YES" ); return YES; } return NO; { } Security.frameworkも参照しておく必要がある 21
  22. 22. 正しい証明書のサイト(2) - (void) connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { NSLog( @"Calling: connection:didReceiveAuthenticationChallenge: %@", challenge ); NSURLCredential *credential = [NSURLCredential credentialForTrust: secTrustRef]; [[challenge sender] useCredential: credential forAuthenticationChallenge:challenge]; } 認証関連メソッドに対応することで接続できる 確認できない証明書にも対応 urlString = https://msyk.net/ Calling: connection:willSendRequest:redirectResponse: (null) Calling: connectionShouldUseCredentialStorage: Calling: connection:canAuthenticateAgainstProtectionSpace: auth method=NSURLAuthenticationMe ---Return YES Calling: connection:didReceiveAuthenticationChallenge: <NSURLAuthenticationChallenge: 0x4d0818 Calling: connection:didReceiveResponse: status code=200 Calling: connection:didReceiveData: Calling: connectionDidFinishLoading: receivedData = <html lang="ja"> 22
  23. 23. Authentication 23
  24. 24. 確認できない証明書(エラーにする場合) SecTrustEvaluate関数の戻り値 • kSecTrustResultRecoverableTrustFailureの場合にNOを返す 基本3メソッドではこれと同じ状態 urlString = https://coolnotify.com/ Calling: connection:willSendRequest:redirectResponse: (null) Calling: connectionShouldUseCredentialStorage: Calling: connection:canAuthenticateAgainstProtectionSpace: auth method=NSURLAuthenticationMethodServerTrust/host=coolnotify.com Calling: connection:didFailWithError: Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid.You might be connecting to a server that is pretending to be “coolnotify.com” which could put your confidential information at risk." UserInfo=0x4b232e0 {NSErrorFailingURLStringKey=https://coolnotify.com/, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, NSErrorFailingURLKey=https://coolnotify.com/, NSLocalizedDescription=The certificate for this server is invalid.You might be connecting to a server that is pretending to be “coolnotify.com” which could put your confidential information at risk., NSUnderlyingError=0x4b22c10 "The certificate for this server is invalid.You might be connecting to a server that is pretending to be “coolnotify.com” which could put your confidential information at risk.", NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 24
  25. 25. - (void) connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { NSLog( @"Calling: connection:didReceiveAuthenticationChallenge: %@", challenge ); if ( [challenge previousFailureCount] == 0 ) { NSURLCredential *credential = [NSURLCredential credentialWithUser: @"te" password: @"te" persistence: NSURLCredentialPersistenceNone]; [[challenge sender] useCredential: credential forAuthenticationChallenge:challenge]; } else if ( [challenge previousFailureCount] == 1 ) { NSURLCredential *credential = [NSURLCredential credentialWithUser: @"msyk" password: @"12345678" persistence: NSURLCredentialPersistenceNone]; [[challenge sender] useCredential: credential forAuthenticationChallenge:challenge]; } else { [[challenge sender] cancelAuthenticationChallenge: challenge]; } } 25
  26. 26. 認証に失敗する場合 urlString = https://msyk.net/iphone/ Calling: connection:willSendRequest:redirectResponse: (null) Calling: connectionShouldUseCredentialStorage: Calling: connection:canAuthenticateAgainstProtectionSpace: auth method=NSURLAuthenticationMethodServerTrust/host=msyk.net ---Return YES Calling: connection:didReceiveAuthenticationChallenge: <NSURLAuthenticationChallenge: 0x4b25fd0 Calling: connection:canAuthenticateAgainstProtectionSpace: auth method=NSURLAuthenticationMethodDefault/host=msyk.net ---Return YES Calling: connection:didReceiveAuthenticationChallenge: <NSURLAuthenticationChallenge: 0x4b2413 Calling: connection:canAuthenticateAgainstProtectionSpace: auth method=NSURLAuthenticationMethodDefault/host=msyk.net ---Return YES Calling: connection:didReceiveAuthenticationChallenge: <NSURLAuthenticationChallenge: 0x9b00b2 Calling: connection:didFailWithError: Error Domain=NSURLErrorDomain Code=-1012 "The operat couldn’t be completed. (NSURLErrorDomain error -1012.)" UserInfo=0x890d7e0 {NSErrorFailingURLKey=https://msyk.net/iphone/, NSErrorFailingURLStringKey=https://msyk.net/ iphone/} 26
  27. 27. 認証に1度失敗し、2度目に成功する場合 urlString = https://msyk.net/iphone/ Calling: connection:willSendRequest:redirectResponse: (null) Calling: connectionShouldUseCredentialStorage: Calling: connection:canAuthenticateAgainstProtectionSpace: auth method=NSURLAuthenticationMethodServerTrust/host=msyk.net ---Return YES Calling: connection:didReceiveAuthenticationChallenge: <NSURLAuthenticationChallenge: 0x9a030e0 Calling: connection:canAuthenticateAgainstProtectionSpace: auth method=NSURLAuthenticationMethodDefault/host=msyk.net ---Return YES Calling: connection:didReceiveAuthenticationChallenge: <NSURLAuthenticationChallenge: 0x700ae90 Calling: connection:canAuthenticateAgainstProtectionSpace: auth method=NSURLAuthenticationMethodDefault/host=msyk.net ---Return YES Calling: connection:didReceiveAuthenticationChallenge: <NSURLAuthenticationChallenge: 0x4e0a6f0 Calling: connection:didReceiveResponse: status code=200 Calling: connection:didReceiveData: Calling: connectionDidFinishLoading: receivedData = <?xml version="1.0" encoding="UTF-8"?>… 27
  28. 28. その他 なぜかdidCancelAuthenticationChallenge:はコールさ れなかった connectionShouldUseCredentialStorageの返り値に よる違いないとしか思えない 28
  29. 29. まとめ NSURLConnectionはネットワークに関係なく生成 didReceiveResponse:メソッドでステータスコード didFailWithError:が呼び出されれば通信エラー 認証への対応はメソッドへの応答として記述する 認証とSSLの両方があるときには要注意 29

×