iOS 新浪微博客户端Demo实践之(一)OAuth2.0认证

继续学习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。

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的代码,通过下面这段代码就可以显示授权页。

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

上面authorize大概就是这样了,那么现在的问题是,如何获取返回的数据呢?从官方API文档中的示例中,我们知道:授权后,会重定向到另一个URL ,而这个URL中就包含了我们上面所说的要返回的数据(重点是code这个参数)。

下面先贴一段代码,这个代码包含了获取重定向的URL,从这个URL中截取code参数值,将code这个参数值添加到access_token这个API后调用,调用后获取返回的参数,对返回的参数进行处理进而获取access_token。(所以这段代码要处理的问题有点多)

第二个API access token调用的URL具体参考官方文档和参看上文第一个API的URL。

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
    
    NSURL *backURL = [request URL];  //接受重定向的URL
    NSString *backURLString = [backURL absoluteString];
    
    //判断是否是授权调用返回的url
    if ([backURLString hasPrefix:@"http://www.baidu.com/?"]) {
        NSLog(@"back url string :%@",backURLString);
        
        //找到”code=“的range
        NSRange rangeOne;
        rangeOne=[backURLString rangeOfString:@"code="];
        
        //根据他“code=”的range确定code参数的值的range
        NSRange range = NSMakeRange(rangeOne.length+rangeOne.location, backURLString.length-(rangeOne.length+rangeOne.location));
        //获取code值
        NSString *codeString = [backURLString substringWithRange:range];
        NSLog(@"code = :%@",codeString);
        
        //access token调用URL的string
        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="];
        [muString appendString:codeString];
        NSLog(@"access token url :%@",muString);
        
        //第一步,创建URL
        NSURL *urlstring = [NSURL URLWithString:muString];
        //第二步,创建请求
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:urlstring cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
        [request setHTTPMethod:@"POST"];//设置请求方式为POST,默认为GET
        NSString *str = @"type=focus-c";//设置参数
        NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
        [request setHTTPBody:data];
        //第三步,连接服务器
        NSData *received = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
        NSString *str1 = [[NSString alloc]initWithData:received encoding:NSUTF8StringEncoding];
        NSLog(@"Back String :%@",str1);
        
        //如何从str1中获取到access_token
        NSDictionary *dictionary = [str1 objectFromJSONString];
        NSLog(@"access token is:%@",[dictionary objectForKey:@"access_token"]);
        
    }
    return YES;
}

这个程序运行的结果

2013-04-14 15:46:14.798 OAuthDemo[350:c07] back url string :http://www.baidu.com/?state=authorize&code=a6146547f981199c07348837b0629d5d
2013-04-14 15:46:14.799 OAuthDemo[350:c07] code = :a6146547f981199c07348837b0629d5d
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
2013-04-14 15:46:15.059 OAuthDemo[350:c07] Back String :{"access_token":"2.00QF7O9Cn7SuKDdeaf7e6529rPILeC","remind_in":"157679999","expires_in":157679999,"uid":"2249439934"}
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的值了。

typedef struct _NSRange {
      NSUInteger location;
      NSUInteger length;
} NSRange;
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返回的参数

{
       "access_token": "ACCESS_TOKEN",
       "expires_in": 1234,
       "remind_in":"798114",
       "uid":"12341234"
 }

这里接收这些数据是放在string里面,显然这些是json类型,那么这里对其的处理是采用jsonkit这个第三方类库,所以要导入这个类库,使用过程中可能会遇到ARC的问题,就是在ARC的项目工程中要对这个第三方类库添加ARC的特性。

这里使用的方法是

 - (id)objectFromJSONString;把这些数据放到dictionary里面方便分离出access_token.

完成,结合给出的程序运行结果应该可以理解了。

你可能感兴趣的:(iOS 新浪微博客户端Demo实践之(一)OAuth2.0认证)