2012年4月28日 星期六

HTTPS加密的V.K克鋼琴大賽

第一屆琴之翼V.K克國際鋼琴大賽 即將開始,



可惜彼得潘沉迷於App開發多年,
早已忘了如何彈琴。
但是,
彼得潘的字典裡沒有放棄呀,
為了提醒自己練習,
彼得潘決定將比賽的圖片收藏於Server,
每天經由iPhone連到Server觀看比賽圖片,
提醒自己比賽日期的逼近。

接下來彼得潘將示範如何經由iPhone存取遠在天邊Server上的圖片。
存取圖片沒什麼特別,
然而當它是https時,
就有些值得一提的密技了。

1. 經由https下載圖片

NSString *str = @"https://www.deeplove.com/~peterpan/vk/vk.jpg";
NSURL *url = [NSURL URLWithString:str];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES];
view raw gistfile1.m hosted with ❤ by GitHub
2. 宣告儲存下載資料的receiveData

我們從遙遠天邊網路下載的資料為NSData型別,由於一張圖片可能很大,我們將收到一連串的NSData物件,因此我們宣告NSMutableData型別的receiveData,利用它蒐集所有收到的NSData物件。一定要湊齊構成圖片的所有NSData,美美的圖片才能完整呈現。

- (void)viewDidLoad
{
[super viewDidLoad];
receiveData = [[NSMutableData alloc] init];
}
view raw gistfile1.m hosted with ❤ by GitHub

3. 實作NSURLConnectionDataDelegate和NSURLConnectionDelegate宣告的接收資料相關callback method。

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(@"%s", __PRETTY_FUNCTION__);
[receiveData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"%s", __PRETTY_FUNCTION__);
UIImage *image = [[UIImage alloc] initWithData:receiveData];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 480, 300)];
imageView.image = image;
imageView.contentMode = UIViewContentModeScaleAspectFit;
[self.view addSubview:imageView];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"%s", __PRETTY_FUNCTION__);
}
view raw gistfile1.m hosted with ❤ by GitHub
執行App:
https果然不是好惹的,
我們完全下載不到任何資料,

connection:didFailWithError:的訊息殘酷地出現在我們眼前。

-[TestHttpsViewController connection:didFailWithError:]

4. 破解https


- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
NSLog(@"%s", __PRETTY_FUNCTION__);
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
NSLog(@"%s", __PRETTY_FUNCTION__);
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
NSLog(@"%s", __PRETTY_FUNCTION__);
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
view raw gistfile1.m hosted with ❤ by GitHub
在iOS 5之後, 破解https變得更容易了, 只要實作connection:willSendRequestForAuthenticationChallenge:。
但在iOS 5之前, 稍微麻煩點, 需要實作以下2個method。 connection:canAuthenticateAgainstProtectionSpace:
connection:didReceiveAuthenticationChallenge:

執行App:


距離2012.8.11還有約100天。
志在參加,
還要得獎。
接下來彼得潘要白天寫App,晚上練琴了!

沒有留言:

張貼留言