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