OAuth授權分四步:
第一步,應用向服務提供方申請請求令牌(Request Token),服務提供方驗證通過后將令牌返回。這個步驟由于涉及到應用帳號密碼,在應用的服務端發起,所以這個步驟對用戶透明。
第二步,應用使用請求令牌讓瀏覽器重定向到服務提供方進行登錄驗證和授權。服務提供方校驗請求令牌,將第三方的資料顯示給用戶,提示用戶選擇同意或拒絕此次授權。如果用戶同意授權,發放已授權令牌并將用戶引導到當前應用的注冊地址。這個步驟從重定向開始到引導回注冊地址之前,應用方并不參與用戶身份校驗和授權過程,確保第三方不可獲得用戶的真實帳號密碼。
第三步,用已授權令牌向服務提供方換取ATOK。第三方應用需在服務端發起請求,用帳號密碼和上一步的令牌換取ATOK,這個步驟對用戶而言也是透明的。如果前兩步分別是讓服務提供方認證應用和用戶,那這步就是用戶和服務提供方再次認證第三方應用。因為用戶瀏覽器將第二步的結果重定向到第三步,除非用戶DNS被劫持,否則就能確保重定向到的是合法的地址。曾經我很困惑在用戶授權之后為何不直接返回ATOK而需要再次換取,估計是出于對ATOK的安全考慮,用戶瀏覽器一端存在太多的可能性讓ATOK泄漏,最安全的辦法還是讓第三方服務端來獲取和保管ATOK。
第四步,用ATOK作為令牌訪問受保護資源。很多時候,權限是有多種類別的。ATOK包含了某個用戶對某個應用的授權憑據,準確的說,ATOK對應用戶授權時所賦予的一系列權限的集合。所以在這一步,除了校驗ATOK的合法性之外,服務提供方還需對該ATOK是否擁有足夠的權限執行被保護操作進行判斷。



(引述別人的話)
如果你開車去酒店赴宴,你經常會苦于找不到停車位而耽誤很多時間。是否有好辦法可以避免這個問題呢?有的,聽說有一些豪車的車主就不擔心這個問題。豪車一般配備兩種鑰匙:主鑰匙和泊車鑰匙。當你到酒店后,只需要將泊車鑰匙交給服務生,停車的事情就由服務生去處理。與主鑰匙相比,這種泊車鑰匙的使用功能是受限制的:它只能啟動發動機并讓車行駛一段有限的距離,可以鎖車,但無法打開后備箱,無法使用車內其他設備。這里就體現了一種簡單的“開放授權”思想:通過一把泊車鑰匙,車主便能將汽車的部分使用功能(如啟動發動機、行駛一段有限的距離)授權給服務生。

NSString *string = [NSString stringWithFormat:@"https://api.weibo.com/oauth2/authorize?client_id=%@&redirect_uri=%@&display=mobile",APPKEY,REDIRECT_URL];NSURL *url = [NSURL URLWithString:string];//用戶授權請求NSURLRequest *request = [NSURLRequest requestWithURL:url]; //加載請求界面[_webView loadRequest:request];
執行上面的代碼我們會調出下面的界面


點擊授權的時候,我們可以在代理方法中打印中請求對象的url.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ NSLog(@"網頁加載請求的時候加載此方法"); //根據請求對象,獲取請求url //absoluteString把url轉化成字符串 NSString *string = request.URL.absoluteString; NSLog(@"%@",string); return YES;}打印信息為:
2015-09-22 13:12:14.339 weibo[1907:60b] http://www.survivalescaperooms.com/wangyaoguo?code=16cca5f05d27854d0341c76cb334390e
我們可以提取出code信息。
然后根據code,發起請求,獲取access_token,然后根據access_token發起請求,獲取微博數據。
下面的代碼是發一條微博的代碼段:
#import "ViewController.h"
#import "ASIFormDataRequest.h"
#import "sendViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *access = [[NSUserDefaults standardUserDefaults] objectForKey:@"access_token"];
if (access.length > 0)
{
UIWindow *window = [UIapplication sharedApplication].delegate.window;
sendViewController *send = [[sendViewController alloc]init];
window.rootViewController = send;
}
else
{
[self loadLoginScreen];
}
}
//載入登錄界面
-(void)loadLoginScreen
{
NSString *string = [NSString stringWithFormat:@"https://api.weibo.com/oauth2/authorize?client_id=%@&redirect_uri=%@&display=mobile",APPKEY,REDIRECT_URL];
NSURL *url = [NSURL URLWithString:string];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[_webView loadRequest:request];
_webView.delegate = self;
}
//webview代理方法頁面載入時調用該方法
//根據相關參數,向服務器發起請求,獲取access_token信息
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSString *string = request.URL.absoluteString;
NSRange range = [string rangeOfString:@"code"];
if (range.location != NSNotFound)
{
NSString *code = [string componentsSeparatedByString:@"code="][1];
NSURL *url = [NSURL URLWithString:@"https://api.weibo.com/oauth2/access_token"];
ASIFormDataRequest *formRequest = [ASIFormDataRequest requestWithURL:url];
formRequest.tag = 10;
[formRequest setPostValue:APPKEY forKey:@"client_id"];
[formRequest setPostValue:APPSECRET forKey:@"client_secret"];
[formRequest setPostValue:@"authorization_code" forKey:@"grant_type"];
[formRequest setPostValue:code forKey:@"code"];
[formRequest setPostValue:REDIRECT_URL forKey:@"redirect_uri"];
formRequest.delegate = self;
[formRequest startAsynchronous];
}
return YES;
}
//請求完成是調用,獲取到access_token
- (void)requestFinished:(ASIHTTPRequest *)request;
{
if (request.tag == 10)
{
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:request.responseData options:NSJSONReadingMutableContainers error:nil];
//獲取數據的通行證(令牌)
_accessToken = [dic objectForKey:@"access_token"];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:_accessToken forKey:@"access_token"];
}
sendViewController *send = [[sendViewController alloc]init];
[self presentViewController:send animated:YES completion:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end

點擊發送按鈕:
- (IBAction)sendWeibo:(id)sender{ NSString *content = _textView.text; if (content.length > 0) { ASIFormDataRequest *sendRequest = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:@"https://api.weibo.com/2/statuses/update.json"]]; NSString *accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:@"access_token"]; [sendRequest setPostValue:accessToken forKey:@"access_token"]; [sendRequest setPostValue:_textView.text forKey:@"status"]; sendRequest.delegate = self; [sendRequest startAsynchronous]; }}

新聞熱點
疑難解答