SDK:https://github.com/JimLiu/WeiboSDK git
這篇文章具體談談在iOS上如何經過新浪微博帳戶登陸應用。 github
在討論這個以前,不得不說到OAuth。這是個什麼玩意呢?按照官方的說法,OAuth是:An open protocol to allow secure API authorization in a simple and standard method from desktop and web applications. web
大概意思是說OAUTH是一種開放的協議,爲桌面程序或者基於BS的web應用提供了一種簡單的,標準的方式去訪問須要用戶受權的API服務。 objective-c
也就是說,經過OAuth,應用或者網站服務能夠獲取用戶的受權,但又不會獲取到用戶的帳戶信息(好比登陸名和密碼)。這裏的受權包括:容許向用戶發送某些信息,容許向用戶提供訪問網站的權限等等。 編程
其實,對於大部分應用來講,只須要驗證用戶是否屬於新浪微博用戶,若是屬於,那也自動是個人用戶,若是不屬於,那麼請用戶就地註冊一個帳戶。換句話說,你將新浪微博的幾億用戶自動認可成爲你的網站用戶,而不須要這幾億用戶經過註冊才能使用你的應用。因此,這是典型的一種YY思想,YY你瞬間得到了幾億用戶!! json
既然OAuth是一個協議,那麼就須要用編程語言去實現它。目前,各類版本的OAuth基本均可以在google code下載到,包括C,C++,C#,JS,PHP等等。固然,確定會有objective-C,不然,我也不會寫這篇文章了。 api
OK,假設已經有了一個版本的Objective-C的OAuth的實現。下面就利用它來實現微博帳戶在iOS上的登陸。 瀏覽器
第一步:註冊應用。 app
能夠經過新浪微博的開放平臺去註冊一個應用。以後你會獲得一個App Key和一個App Secret。擁有它們,你才能夠申請權限。 編程語言
假設你的App Key是「1234567890」,App Secret是「abcdefghijklmnopqrstuvwxyz"
第二步:寫代碼。
將獲取到的OAuth的objective-C版本加入你的project中。將你申請到的Key和Secret作爲兩個變量定義並賦值。
對於OAuth來講,不少細節不須要咱們去關注的,只要知道幾個重要的步驟便可:
1. 建立一個request,這個request包含key和secret的信息,用於向新浪微博申請得到對應用戶的權限。
2. 經過request向新浪微博發出請求,告訴新浪微博說:我是一個合法的註冊過的應用,如今準備向大人您申請得到用戶的權限,請您高擡貴手。
3. 得到未受權的 Request Key。這個得到未受權的 Request Key就至關於放行條,也就是新浪微博容許你開始獲取用戶的權限。
4. 根據這個Request Key的內容,得到一個url地址,這個地址頁面就是想登陸你應用的用戶輸入用戶名和密碼的地方。注意的是,這個url是屬於新浪微博爲你的這個應用建立的,是屬於新浪微博的。調用iOS的接口,從瀏覽器打開這個url界面。
5. 用戶在上述登陸界面輸入本身的用戶名和密碼,成功登陸以後(實際上是新浪微博認證此用戶是註冊了新浪微博的用戶),你能夠得到已受權的 Access KEY。這個Access Key就包含了用戶多登陸信息(包括暱稱、用戶ID等等,這裏的暱稱是指用戶顯示在新浪微博上的名字,而不是用戶的登陸名)。
6. 到目前爲止,你已經肯定用戶是新浪微博的用戶了,天然也是你的應用的用戶(繼續YY),因此接下去,你就趕忙容許用戶登陸成功,進入你的應用主界面,享受你的應用程序了。還愣着幹嗎,翠花,上酸菜!!
找到一個objective-c實現的OAuth,而且對着每一步(第六步除外,第六步是在你本身的project中實現。你總不能讓OAuth給你上酸菜吧),找到實現每一步功能的函數,而後加入你本身的project中。
代碼:
#import <Foundation/Foundation.h> @interface SinaCodePathAndDic : NSObject +(NSString *)writeToFilePath; +(NSMutableDictionary *)code; @end #import "SinaCodePathAndDic.h" @implementation SinaCodePathAndDic +(NSString *)writeToFilePath { NSString *fileName=[NSHomeDirectory() stringByAppendingPathComponent:@"tmp/sinacode.plist"]; return fileName; } +(NSMutableDictionary *)code { NSString *fileName=[NSHomeDirectory() stringByAppendingPathComponent:@"tmp/sinacode.plist"]; NSMutableDictionary * codeDic = [NSMutableDictionary dictionaryWithContentsOfFile:fileName]; return codeDic; } @end #import <Foundation/Foundation.h> #define SinaAppkey @"309949296" #define SinaAppSecret @"a86376995071dc71a8616035c3d89176" #define SinaCOMEBACK_URL @"http://www.m-bao.com" #define URL_Authorize @"https://api.weibo.com/oauth2/authorize" ////使用瀏覽器受權request token (這個url加上參數在瀏覽器執行) #define URL_Access @"https://api.weibo.com/oauth2/access_token" //獲取access token #define URL_SHARE_TEXT @"http://api.t.sina.com.cn/statuses/update.json" #define URL_SHARE_PIC @"https://api.weibo.com/2/statuses/upload.json" #define TOKEN_USER_ID @"token_userId" #define TOKEN_PREFIX @"token_weibo" #define TOKEN_PROVIDER @"token_sina" #import <Foundation/Foundation.h> #import <CommonCrypto/CommonDigest.h> @interface SinaShareURL : NSObject{ } -(id)initWithText:(NSString *)text_; -(id)initWithText:(NSString *)text_ andPic:(UIImage *)pic_; +(BOOL)isDic; @end #import "SinaShareURL.h" #import "SinaKey.h" #import "SinaToken.h" #import "URLEncode.h" #import "JSON.h" #define SHAREURL @"https://api.weibo.com/2/statuses/repost.json" @implementation SinaShareURL +(BOOL)isDic { NSDictionary * DIC=[NSDictionary dictionaryWithDictionary:[SinaToken userDataAndToken]]; if (![DIC valueForKey:@"access_token"]) { return NO; } return YES; } -(id)initWithText:(NSString *)text_ { NSDictionary * DIC=[NSDictionary dictionaryWithDictionary:[SinaToken userDataAndToken]]; NSURL * url_ = [NSURL URLWithString:[NSString stringWithFormat:@"https://api.weibo.com/2/statuses/update.json?access_token=%@",[DIC valueForKey:@"access_token"]]]; NSString * str_ = [NSString stringWithFormat:@"status=%@",[URLEncode encodeUrlStr:text_]]; NSData * data = [str_ dataUsingEncoding:NSUTF8StringEncoding]; NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url_]; [request setHTTPMethod:@"POST"]; [request setHTTPBody:data]; [NSURLConnection connectionWithRequest:request delegate:self]; return self; } -(id)initWithText:(NSString *)text_ andPic:(UIImage *)pic_ { NSDictionary * DIC=[NSDictionary dictionaryWithDictionary:[SinaToken userDataAndToken]]; NSURL * url_ = [NSURL URLWithString:[NSString stringWithFormat:@"https://api.weibo.com/2/statuses/upload.json?access_token=%@",[DIC valueForKey:@"access_token"]]]; NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url_]; UIImage * image_ = pic_; NSData * imgData_ = UIImageJPEGRepresentation(image_, 0); NSString *boundary = @"AAAVVVAAA"; NSString *boundaryEnd = [NSString stringWithFormat:@"\r\n--%@--\r\n",boundary]; NSString *Content_Type = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary]; NSMutableString *bodyString = [NSMutableString stringWithCapacity:100]; [bodyString appendFormat:@"--%@",boundary]; [bodyString appendString:@"\r\nContent-Disposition: form-data; name="status"\r\n\r\n"]; if (text_) { [bodyString appendString:[URLEncode encodeUrlStr:text_]]; } else{ [bodyString appendString:[URLEncode encodeUrlStr:@" "]]; } [bodyString appendFormat:@"\r\n--%@",boundary]; [bodyString appendString:@"\r\nContent-Disposition: form-data; name="pic"; filename="image.jpg"\r\nContent-Type: image/jpeg\r\n\r\n"]; //data NSMutableData *bodyDataWithPic = [NSMutableData dataWithData:[bodyString dataUsingEncoding:NSUTF8StringEncoding]]; [bodyDataWithPic appendData:imgData_]; [bodyDataWithPic appendData:[boundaryEnd dataUsingEncoding:NSUTF8StringEncoding]]; //set header [request setValue:Content_Type forHTTPHeaderField:@"Content-Type"]; [request setValue:[NSString stringWithFormat:@"%d",[bodyDataWithPic length]] forHTTPHeaderField:@"Content-Length"]; [request setHTTPBody:bodyDataWithPic]; [request setHTTPMethod:@"POST"]; [NSURLConnection connectionWithRequest:request delegate:self]; return self; } -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { NSString * str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"asd=%@",[str JSONValue]); // NSLog(@"111%@",data); } -(void)connectionDidFinishLoading:(NSURLConnection *)connection { // NSString * str = [[NSString alloc] initWithData:data_ encoding:NSUTF8StringEncoding]; // NSLog(@"asd=%@",[str JSONValue]); [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; } @end #import <Foundation/Foundation.h> @protocol SinaTokenDeletage <NSObject> - (void)tokenSaveOkayForSina; @end @interface SinaToken : NSObject{ NSMutableData * data; id<SinaTokenDeletage>deletage; } @property (nonatomic,assign) id<SinaTokenDeletage>deletage; - (void)getToken; -(void)removeToken; +(NSString *)writeToFilePath; +(NSMutableDictionary *)userDataAndToken; @end #import "SinaToken.h" #import "SinaUrl.h" #import "JSON.h" @implementation SinaToken @synthesize deletage; - (void)dealloc { if (data) { [data release]; } [super dealloc]; } +(NSString *)writeToFilePath { NSString *fileName=[NSHomeDirectory() stringByAppendingPathComponent:@"tmp/sinauser.data"]; return fileName; } +(NSMutableDictionary *)userDataAndToken { NSString *fileName=[NSHomeDirectory() stringByAppendingPathComponent:@"tmp/sinauser.data"]; NSData * data = [NSData dataWithContentsOfFile:fileName]; NSString * dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSMutableDictionary * userDic = [dataStr JSONValue]; NSLog(@"%@",userDic); return userDic; } - (void)getToken { data = [[NSMutableData alloc] init]; NSURL * url_ = [NSURL URLWithString:[SinaUrl SinaGetToKenURLString]]; NSLog(@"cc=%@",[SinaUrl SinaGetToKenURLString]); NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url_]; [request setHTTPMethod:@"POST"]; [NSURLConnection connectionWithRequest:request delegate:self]; } -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)_data { // NSLog(@"22222%@",data); [data appendData:_data]; } -(void)connectionDidFinishLoading:(NSURLConnection *)connection { NSLog(@"!!!!!!!!!!!%@,",data); NSString *fileName=[NSHomeDirectory() stringByAppendingPathComponent:@"tmp/sinauser.data"]; NSLog(@"%@,",data); [data writeToFile:fileName atomically:YES]; if (deletage) { [deletage tokenSaveOkayForSina]; } } -(void)removeToken { NSFileManager* fileManager = [NSFileManager defaultManager]; NSString *fileName=[NSHomeDirectory() stringByAppendingPathComponent:@"tmp/sinauser.data"]; [fileManager removeItemAtPath:fileName error:nil]; NSLog(@"%@",fileName); } @end #import <Foundation/Foundation.h> #import "SinaKey.h" @interface SinaUrl : NSObject{} +(NSString *)SinaUrlString; +(NSString *)SinaGetToKenURLString; //+(NSString *)SinaShareUrlString; @end #import "SinaUrl.h" #import "SinaCodePathAndDic.h" @implementation SinaUrl +(NSString *)SinaUrlString{ NSString * parameter = @""; NSMutableArray * urlArray = [[NSMutableArray alloc] init]; [urlArray addObject:[NSString stringWithFormat:@"client_id=%@",SinaAppkey]]; [urlArray addObject:[NSString stringWithFormat:@"redirect_uri=%@",SinaCOMEBACK_URL]]; [urlArray addObject:[NSString stringWithFormat:@"display=%@",@"mobile"]]; for (int i=0; i<[urlArray count]; i++) { if (i==0) { parameter = [[parameter stringByAppendingString:@"?"] stringByAppendingString:[urlArray objectAtIndex:i]]; }else{ parameter = [[parameter stringByAppendingString:@"&"] stringByAppendingString:[urlArray objectAtIndex:i]]; } } NSString * urlString = [URL_Authorize copy]; urlString = [urlString stringByAppendingString:parameter]; [urlArray release]; return urlString; } +(NSString *)SinaGetToKenURLString { NSString * parameter = @""; NSMutableArray * urlArray = [[NSMutableArray alloc] init]; [urlArray addObject:@"grant_type=authorization_code"]; [urlArray addObject:[NSString stringWithFormat:@"code=%@",[[SinaCodePathAndDic code] objectForKey:@"code"]]]; [urlArray addObject:[NSString stringWithFormat:@"client_id=%@",SinaAppkey]]; [urlArray addObject:[NSString stringWithFormat:@"redirect_uri=%@",SinaCOMEBACK_URL]]; [urlArray addObject:[NSString stringWithFormat:@"client_secret=%@",SinaAppSecret]]; for (int i=0; i<[urlArray count]; i++) { if (i==0) { parameter = [[parameter stringByAppendingString:@"?"] stringByAppendingString:[urlArray objectAtIndex:i]]; }else{ parameter = [[parameter stringByAppendingString:@"&"] stringByAppendingString:[urlArray objectAtIndex:i]]; } } NSString * urlString = [URL_Access copy]; urlString = [urlString stringByAppendingString:parameter]; return urlString; } @end #import <UIKit/UIKit.h> #import "MainViewController.h" @protocol SinaWebViewControllerDeletage <NSObject> - (void)hasCodeForSina; @end @interface SinaWebViewController : MainViewController<UIWebViewDelegate>{ UIWebView * web; NSMutableData * data; id<SinaWebViewControllerDeletage>deletage; } @property (nonatomic,assign) id<SinaWebViewControllerDeletage>deletage; @end #import "SinaWebViewController.h" #import "SinaUrl.h" #import "SinaCodePathAndDic.h" @implementation SinaWebViewController @synthesize deletage; - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } -(void)dealloc { [web release]; [data release]; [super dealloc]; } - (void)didReceiveMemoryWarning { // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; // Release any cached data, images, etc that aren't in use. } #pragma mark - View lifecycle -(void)popModeVC { [self dismissModalViewControllerAnimated:YES]; } // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. - (void)viewDidLoad { [super viewDidLoad]; UINavigationBar * myBar_ = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)]; [myBar_ setTintColor:[UIColor orangeColor]]; UINavigationItem * item_ = [[UINavigationItem alloc] initWithTitle:NSLocalizedString(@"新浪認證", nil)]; UIBarButtonItem * buttonItem_ = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"返回", nil) style:UIBarButtonItemStyleBordered target:self action:@selector(popModeVC)]; item_.leftBarButtonItem = buttonItem_; [buttonItem_ release]; [myBar_ pushNavigationItem:item_ animated:NO]; [item_ release]; [self.view addSubview:myBar_]; web = [[UIWebView alloc] initWithFrame:CGRectMake(0, 44, 320, 480)]; [web setDelegate:self]; NSURL * url = [NSURL URLWithString:[SinaUrl SinaUrlString]]; NSLog(@"URL=%@",url); NSURLRequest * re = [NSURLRequest requestWithURL:url]; [web loadRequest:re]; data = [[NSMutableData alloc] init]; [self.view addSubview:web]; } - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSString * urlStr=[[request URL] relativeString]; NSString * str=[[urlStr componentsSeparatedByString:@"?"] objectAtIndex:0]; if ([str isEqualToString:@"http://www.m-bao.com/"]) { NSString * codeStr=[[[[urlStr componentsSeparatedByString:@"code="] objectAtIndex:1] componentsSeparatedByString:@"&"]objectAtIndex:0]; NSMutableDictionary * codeDic = [NSMutableDictionary dictionary]; [codeDic setValue:codeStr forKey:@"code"]; NSLog(@"%@",codeStr); [codeDic writeToFile:[SinaCodePathAndDic writeToFilePath] atomically:YES]; if (deletage) { [deletage hasCodeForSina]; } [self dismissModalViewControllerAnimated:YES]; }else { } return YES; } - (void)webViewDidStartLoad:(UIWebView *)webView { [self webStartLoad]; } - (void)webViewDidFinishLoad:(UIWebView *)webView { [self webFinishLoad]; } - (void)viewDidUnload { [super viewDidUnload]; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return (interfaceOrientation == UIInterfaceOrientationPortrait); } @end