iOS 新浪微部落格戶端Demo實踐之(一)OAuth2.0認證

躍然發表於2014-07-30

繼續學習iOS,這個練習的Sina Weibo Demo。

這個練習程式將分多part實現。下面是第一篇 -- OAuth2.0認證。

下面還是要簡要說一下在程式開發之前的準備,首先要到新浪開發者平臺建立一個移動應用獲得key和secret,注意還有一個要注意的是在管理中心的應用資訊裡的高階資訊中編輯OAuth2.0 授權設定的授權回撥頁。

在認證這一部分會用到兩個API ,分別是請求授權和獲取授權。(連結地址是:http://open.weibo.com/wiki/Oauth2/authorize   和   http://open.weibo.com/wiki/OAuth2/access_token )。而這二者又是什麼關係呢?首先要通過authorize之後再拿到access token。而access token是以後呼叫相關API的必要引數。在這兩個API的文件中可以知道access token的呼叫引數中含有authorize呼叫後返回的code引數(具體看文件)。

下面介紹authorize這個API。

  1. https://api.weibo.com/oauth2/authorize?client_id=2909579077&redirect_uri=http://www.baidu.com&response_type=code&display=mobile&state=authorize  

下面解釋一下這個URL是怎麼傳參的吧,首先是在認證url:   https://api.weibo.com/oauth2/authorize的後面新增一個問號?然後傳遞各個引數和值,每個引數都是用&隔開。

引數說明:

其中client_id就是你申請建立應用的key;redirect_uri就是前面提到的在授權設定中的授權回撥頁,注意要保持二者一致;response_type填寫code,這個code就是在授權的時候會返回的一串code,這一串code會在第二個API呼叫中作為引數值(注意:這個code是變化的,也就說每次授權的時候是動態變化的;而之後我們要獲取的access token這個是固定的),當然還可以填寫成token,那麼在授權返回的url地址中就包含了access token(關於這個下面再詳述);display填寫mobile(移動終端應用);在最後的state這個引數是可選的,也就是或可以省去,加上後,在授權返回的資料中就包含這個引數項。那麼通過這個url,就可以在微博view中載入到一個授權頁面,可以通過瀏覽器輸入這個url驗證是否正確。

在授權後會得到的引數有:


返回值欄位 欄位型別 欄位說明
code string 用於呼叫access_token,介面獲取授權後的access token。
state string 如果傳遞引數,會回傳該引數。

下面是載入webview的程式碼,通過下面這段程式碼就可以顯示授權頁。

  1. - (void)viewDidLoad  
  2. {  
  3.     [super viewDidLoad];  
  4.     // Do any additional setup after loading the view, typically from a nib.  
  5.     NSString *urlString = @"https://api.weibo.com/oauth2/authorize?client_id=2909579077&redirect_uri=http://www.baidu.com&response_type=code&display=mobile&state=authorize";  
  6.     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]];  
  7.     [self.webView setDelegate:self];  
  8.     [_webView loadRequest:request];      
  9. }  

上面authorize大概就是這樣了,那麼現在的問題是,如何獲取返回的資料呢?從官方API文件中的示例中,我們知道:授權後,會重定向到另一個URL ,而這個URL中就包含了我們上面所說的要返回的資料(重點是code這個引數)。

下面先貼一段程式碼,這個程式碼包含了獲取重定向的URL,從這個URL中擷取code引數值,將code這個引數值新增到access_token這個API後呼叫,呼叫後獲取返回的引數,對返回的引數進行處理進而獲取access_token。(所以這段程式碼要處理的問題有點多)

第二個API access token呼叫的URL具體參考官方文件和參看上文第一個API的URL。

  1. - (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {  
  2.       
  3.     NSURL *backURL = [request URL];  //接受重定向的URL  
  4.     NSString *backURLString = [backURL absoluteString];  
  5.       
  6.     //判斷是否是授權呼叫返回的url  
  7.     if ([backURLString hasPrefix:@"http://www.baidu.com/?"]) {  
  8.         NSLog(@"back url string :%@",backURLString);  
  9.           
  10.         //找到”code=“的range  
  11.         NSRange rangeOne;  
  12.         rangeOne=[backURLString rangeOfString:@"code="];  
  13.           
  14.         //根據他“code=”的range確定code引數的值的range  
  15.         NSRange range = NSMakeRange(rangeOne.length+rangeOne.location, backURLString.length-(rangeOne.length+rangeOne.location));  
  16.         //獲取code值  
  17.         NSString *codeString = [backURLString substringWithRange:range];  
  18.         NSLog(@"code = :%@",codeString);  
  19.           
  20.         //access token呼叫URL的string  
  21.         NSMutableString *muString = [[NSMutableString alloc] initWithString:@"https://api.weibo.com/oauth2/access_token?client_id=2909579077&client_secret=90184f4606fd04f449131ea4fbdb74c4&grant_type=authorization_code&redirect_uri=http://www.baidu.com&code="];  
  22.         [muString appendString:codeString];  
  23.         NSLog(@"access token url :%@",muString);  
  24.           
  25.         //第一步,建立URL  
  26.         NSURL *urlstring = [NSURL URLWithString:muString];  
  27.         //第二步,建立請求  
  28.         NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:urlstring cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];  
  29.         [request setHTTPMethod:@"POST"];//設定請求方式為POST,預設為GET  
  30.         NSString *str = @"type=focus-c";//設定引數  
  31.         NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];  
  32.         [request setHTTPBody:data];  
  33.         //第三步,連線伺服器  
  34.         NSData *received = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];  
  35.         NSString *str1 = [[NSString alloc]initWithData:received encoding:NSUTF8StringEncoding];  
  36.         NSLog(@"Back String :%@",str1);  
  37.           
  38.         //如何從str1中獲取到access_token  
  39.         NSDictionary *dictionary = [str1 objectFromJSONString];  
  40.         NSLog(@"access token is:%@",[dictionary objectForKey:@"access_token"]);  
  41.           
  42.     }  
  43.     return YES;  
  44. }  

這個程式執行的結果

  1. 2013-04-14 15:46:14.798 OAuthDemo[350:c07] back url string :http://www.baidu.com/?state=authorize&code=a6146547f981199c07348837b0629d5d  
  2. 2013-04-14 15:46:14.799 OAuthDemo[350:c07] code = :a6146547f981199c07348837b0629d5d  
  3. 2013-04-14 15:46:14.799 OAuthDemo[350:c07] access token url :https://api.weibo.com/oauth2/access_token?client_id=2909579077&client_secret=90184f4606fd04f449131ea4fbdb74c4&grant_type=authorization_code&redirect_uri=http://www.baidu.com&code=a6146547f981199c07348837b0629d5d  
  4. 2013-04-14 15:46:15.059 OAuthDemo[350:c07] Back String :{"access_token":"2.00QF7O9Cn7SuKDdeaf7e6529rPILeC","remind_in":"157679999","expires_in":157679999,"uid":"2249439934"}  
  5. 2013-04-14 15:46:15.061 OAuthDemo[350:c07] access token is:2.00QF7O9Cn7SuKDdeaf7e6529rPILeC  

下面對這段程式碼進行解說一下:

1、首先我們在(BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType  這個函式中接受授權重定向後的URL。

2、但是這個函式在授權過程中可能會經過多次重定向,而我們需要的是包含code引數的那個重定向URL,所以要找到這個URL,我們是看他重定向後的這個URL是否包含@"http://www.baidu.com/?"這個字首,在包含的這個字首的URL中就包含返回的資料(code)。

3、接著就是從這個URL中分離中出code的引數值。方法是這樣的,首先確定“code=”的range,然後由這個range再來確定code引數值的range,這樣就找到code的值了。

  1. typedef struct _NSRange {  
  2.       NSUInteger location;  
  3.       NSUInteger length;  
  4. } NSRange;  
  5. Description A structure used to describe a portion of a series—such as characters in a string or objects in an NSArray object.  


4、code的引數值找到了,接下來就是對access token這個API 的呼叫了,採用的是同步POST請求

5、最後的一步就是對access token這個API 呼叫返回的資料分離出access_token這個引數。

注意到這個api返回的引數

  1. {  
  2.        "access_token""ACCESS_TOKEN",  
  3.        "expires_in": 1234,  
  4.        "remind_in":"798114",  
  5.        "uid":"12341234"  
  6.  }  

這裡接收這些資料是放在string裡面,顯然這些是json型別,那麼這裡對其的處理是採用jsonkit這個第三方類庫,所以要匯入這個類庫,使用過程中可能會遇到ARC的問題,就是在ARC的專案工程中要對這個第三方類庫新增ARC的特性。

這裡使用的方法是

[objc] view plaincopy
  1. <span style="background-color:rgb(255,255,255)"> - (id)objectFromJSONString;把這些資料放到dictionary裡面方便分離出access_token.</span>  

完成,結合給出的程式執行結果應該可以理解了。


感謝原作者:crayondeng

原文連結:http://blog.csdn.net/crayondeng/article/details/8805381

相關文章