当前位置: 代码迷 >> 移动平台 >> 豆瓣OAuth2.0针对腾挪平台的第三方应用授权
  详细解决方案

豆瓣OAuth2.0针对腾挪平台的第三方应用授权

热度:2993   发布时间:2013-02-26 00:00:00.0
豆瓣OAuth2.0针对移动平台的第三方应用授权

最近无聊找一些开放平台提供的资源,做一些第三方应用练练手。

对于微博类开放平台,因为很早前还在做Android的时候做过一次,没什么新鲜感。

恰巧本人以前玩豆瓣,对于豆瓣社区的一些资源还是比较感兴趣,比如小组,评论,书电影音乐资源。

虽然最后浏览完API后,发现已开发的几个接口,相对来说做一个扩展应用的真心比较乏力。

比如关于同城的api提供 比较给力,但是你发现豆瓣自己有客户端了。

豆瓣广播,类微博一样,也有了官方的客户端了。

最后觉得用户活跃度最高的小组,却没有提供,同样的一些书影评资讯也只是提供了一个搜索的接口。

我想要一些,比如热门影讯,评论,最后发现只能调用RSS来实现,并且坑爹的单条资讯内容,内容只有描述,没有详情。


不过既然已经做了,就当做练手,上一个项目一直做的网络层,逻辑层,数据处理,这会刚好熟练下UI控件。


下面我们先看下豆瓣关于OAuth2.0中:

豆瓣支持三种OAuth2.0的授权流程:直接在浏览器中运行的Javascript应用的授权流程(user-agent flow)有服务器的WEB应用的授权流程(server-side flow)桌面客户端应用、移动客户端应用的授权流程(native-application flow)

http://developers.douban.com/wiki/?title=oauth2豆瓣文档。

因为ios作为移动客户端应用,我们主要看第三块。熟悉了大致情况后,准备做授权模块。


我们先看下我客户端实现的效果图。


1.首先,我们看文档的api文档描述

flow 与 native-application flow这两种授权流程基本相同,需要通过两步来获取access_token。获取authorization_code通过在浏览器中访问下面的地址,来引导用户授权,并获得authorization_codehttps://www.douban.com/service/auth2/auth参数:参数名称	参数说明client_id	必选参数,应用的唯一标识,对应于APIKeyredirect_uri	必选参数,用户授权完成后的回调地址,应用需要通过此回调地址获得用户的授权结果。此地址必须与在应用注册时填写的回调地址一致。response_type	必选参数,此值可以为 code 或者 token 。在本流程中,此值为 codescope	可选参数,申请权限的范围,如果不填,则使用缺省的scope。如果申请多个scope,使用逗号分隔。state	可选参数,用来维护请求和回调状态的附加字符串,在授权完成回调时会附加此参数,应用可以根据此字符串来判断上下文关系。注意:此请求必须是HTTP GET方式例如:https://www.douban.com/service/auth2/auth?  client_id=0b5405e19c58e4cc21fc11a4d50aae64&  redirect_uri=https://www.example.com/back&  response_type=code&  scope=shuo_basic_r,shuo_basic_w返回结果:当用户拒绝授权时,浏览器会重定向到redirect_uri,并附加错误信息https://www.example.com/back?error=access_denied当用户同意授权时,浏览器会重定向到redirect_uri,并附加autorization_codehttps://www.example.com/back?code=9b73a4248

https://www.douban.com/service/auth2/auth就是我们这个授权页面,加载这个页面时,需要在url地址中传入一些参数(应用key啊什么的,相信大家都了解)因此我们需要自己内嵌一个UIWebView控件,(当然,有人会说直接跳转到浏览器不就得了)

这个等会会具体提到,因为我们要截取一个token值。

ps:

这边主要说一下这个重定向地址参数的问题:redirect_uri=https://www.example.com/back

这个参数在申请应用时也会用到,它意义,就当我们在授权页面“授权”或是“拒绝”后,浏览器自动会重定向跳转到这个地址页面,并且在这个url地址中附加了一些

回调信息,这点上面也提到了(比如你点击了拒绝,https://www.example.com/back?error=access_denied,点击了授权,成功的话,就返回token值)

其实这个重定向参数的意义更多我觉得其实是为了web类应用设定的,因为web应用最基础的容器就是一个浏览器,当无论授权或是拒绝后,离开了授权界面,

我们必须提供一个新的地址让浏览器来跳转啊,但是,在移动应用中,其实是并不需要这样的。

因此,你会看到有的资料提示说移动类客户端可以填写“oob”什么的,而且对于移动类客户端最好的授权方式也是如此,并不需要一个重定向地址,直接返回值

不是感觉会更好,这边我们就暂时看api流程提供的来吧。

说了半天,那这个参数到底怎么填呢,(并且豆瓣申请时必须要填,且它还会自动检查格式,必须是url地址)。

考虑到,我们的移动类应用对于这个重定向地址其实并没有实际用处,只是做为一个载体返回一些附加信息,我们会需要这些附加信息。

因此我就根据自个爱好写了一个"https://www.nono_lilith.com";

好了,对于其他几个参数,具体看文档。

比如我的授权url地址+参数的结果:

    NSString *urlpath = [NSString stringWithFormat:@"https://www.douban.com/service/auth2/auth?client_id=%@&redirect_uri=%@&response_type=token&display=popup",_api_key,_redirect];.

2.然后就是授权和拒绝操作后的返回了。

按照我们客户端的理念,如果授权成功了,那么我们截取获取授权码保存起来,并给用户显示一个授权成功的提示框,关闭这个授权界面。

同样拒绝也一样,我们获取附加值,判断得知是用户的拒绝操作,同样提示或是关闭该界面。

这边就讲到整片文章的核心点了,对于重定向返回的附加参数的截取。

#pragma mark UIWebViewDelegate methods- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{    BOOL b = YES;        NSString *targetUrl = request.URL.absoluteString;    if ([_douban_register isEqualToString:targetUrl]) {//注册,直接跳转浏览器         [[UIApplication sharedApplication] openURL:[NSURL URLWithString:_douban_register]];        b = NO;    }else if ([targetUrl isEqualToString:_resure_url]) {//拒绝授权        b = NO;        [self back];    }        NSRange range = [targetUrl rangeOfString:@"https://www.nono_lilith.com/#access_token="];    if (range.length > 0) {//点击了授权,并且成功了        NSString *tokenMore = [targetUrl substringFromIndex:range.location+range.length];        NSString *token = [[tokenMore componentsSeparatedByString:@"&"] objectAtIndex:0];        NSLog(@"获取的token = %@",token);        _delegate = (NLAppDelegate*)[[UIApplication sharedApplication] delegate];        _delegate.isLogin = YES;        _delegate.token = token;        b = NO;        [self back];    }        return b;}- (void)webViewDidStartLoad:(UIWebView *)webView{    }- (void)webViewDidFinishLoad:(UIWebView *)webView{//    NSString *url =  webView.request.URL.absoluteString;        }- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{    }-(void)back{    [self.navigationController popViewControllerAnimated:YES];}

我这边是利用webview的代理方法来实现截取和跳转。

主要操作都在第一个代理方法中。

该方法会返回一个bool值,来控制webview是否要发生请求。

NSString *targetUrl = request.URL.absoluteString;

可以获取webview准备加载的url地址。

先跳过前几行判断注册什么的注释,主要看截取重定向url和他附加的值。

 NSRange range = [targetUrl rangeOfString:@"https://www.nono_lilith.com/#access_token="];    if (range.length > 0) {//点击了授权,并且成功了        NSString *tokenMore = [targetUrl substringFromIndex:range.location+range.length];        NSString *token = [[tokenMore componentsSeparatedByString:@"&"] objectAtIndex:0];        NSLog(@"获取的token = %@",token);        _delegate = (NLAppDelegate*)[[UIApplication sharedApplication] delegate];        _delegate.isLogin = YES;        _delegate.token = token;        b = NO;        [self back];    }

具体如何来截取其实都是一些微操作,看你自己想法了。只要能实现。

这段代码其实就是捕获重定向截取tokencode。然后bool设置成NO,就是说不用跳转了,或是直接pop或是取消掉该界面。

然后对于用户拒绝操作的判断

else if ([targetUrl isEqualToString:_resure_url]) {//拒绝授权        b = NO;        [self back];    }这边的NSString *_resure_url =  @"https://www.nono_lilith.com/?error=access_denied";
操作基本同上。


以上基本是豆瓣OAuth2.0授权的一种流程。

这边我们还可以做一些小改进。

从页面看到,我们还能点击的两个操作。

1.豆瓣开放平台条款,如果点击就是跳转到豆瓣首页了(目前测试),因为我们的webview没用返回什么的按钮,因此当看完了条款后用户想授权,

发现回不去那个授权网页界面了~~

同样的还有那个注册操作,会跳转到豆瓣注册界面,首先还是会碰到上面说的这点,更重要的一点,豆瓣注册在选择居住地时,我们内嵌的webview不可提供交互

(可能要开启什么属性或是参数,记得Android时候是开始js属性等等),因此,最好和简单的方法就是跳转到safari浏览器执行相关操作。

因此也就是我上面捕获url地址然后进行跳转操作。

以上就是目前豆瓣OAuth2.0移动客户端授权的一种处理方式,因为我看了好多api其实都在完善和测试中。

最后想说,为毛不开放小组API。





1楼ztx470539152昨天 16:14
能有源码下载地址么
  相关解决方案